Система.NotSupportedException отображается при загрузке изображения

#c# #windows-phone-7.1 #windows-phone-7

#c# #windows-phone-7.1 #windows-phone-7

Вопрос:

В моем приложении пользователь может загрузить фотографию с телефона и опубликовать ее на веб-сайте.Приложение работает хорошо, пока я не обновлю ОС своего телефона до Windows 7.1. После обновления до Windows 7.1 я получаю исключение «System.NotSupportedException» при загрузке изображения.Эта проблема связана с обновлением телефона?Или проблема в моем классе загрузки изображений? Но этот код работает хорошо, пока я не обновлю ОС своего телефона.(я не обновлял свой проект до версии 7.1, только ОС телефона и эмулятор, обновленные до mango) Вот мой код,

 private void ApplicationBarPhotoChooser_Click(object sender, EventArgs e)
    {

            objPhotoChooserTask.Show();

    }
      void objPhotoChooserTask_Completed(object sender, PhotoResult e)
    {
        if (e.TaskResult == TaskResult.OK)
        {
            BitmapImage objBitmapImage = new BitmapImage();
            objBitmapImage.SetSource(e.ChosenPhoto);
            upLoadPhoto(objBitmapImage);

        }
    }
     private void upLoadPhoto(BitmapImage PhotoToUpload)
    {
        if ((Application.Current as App).objTwitterPostMessageContainer == null)
        {
            (Application.Current as App).objTwitterPostMessageContainer = new TwitterPostMessageContainer();
        }
        (Application.Current as App).objTwitterPostMessageContainer.properties = "";
        ImageUploader objImageUploader = new ImageUploader();
        objImageUploader.ms_caption = strAPIKEY;
        objImageUploader.PhotoToPost = PhotoToUpload;
        objImageUploader.PostPhoto();
        timer.Start();
        btnNext.IsEnabled = false;

    }
  

Класс загрузки изображения

 public class ImageUploader
{

    #region class setup



    //local property variables

    private string ms_boundary = string.Empty;

    private string ms_accesstoken = string.Empty;

    private BitmapImage mimg_phototopost;

    public string ms_caption { get; set; }



    // some multipart constants we will use in the strings we create

    private const string Prefix = "--";

    private const string NewLine = "rn";



    public ImageUploader() { }





    public BitmapImage PhotoToPost
    {

        get { return mimg_phototopost; }

        set { mimg_phototopost = value; }

    }





    public string PhotoCaption
    {

        get { return ms_caption; }

        set { ms_caption = value; }

    }



    public String BoundaryString
    {

        get
        {

            if (ms_boundary == string.Empty)

            { ResetBoundaryString(); }

            return ms_boundary;

        }

    }



    public void ResetBoundaryString()
    {

        ms_boundary = "----------------------------"   DateTime.Now.Ticks.ToString("x");

    }



    public String AccessToken
    {

        get

        { return ms_accesstoken; }

        set

        { ms_accesstoken = value; }

    }



    #endregion



    #region Post Data Stuff





    public void PostPhoto()

    //builds a byte array with the image in it and passes it to PostPhotoHTTPWebRequest

    //which sends the data via a POST to facebook
    {

        if (mimg_phototopost != null)
        {
            // PostPhotoHTTPWebRequest(BuildPostData());
            byte[] ba_photo = ImageToByteArray(PhotoToPost);
            PostPhotoHTTPWebRequest(ba_photo);
        }
    }



    private byte[] BuildPostData()

    //Uses the PhotoToPost and BoundaryString to build a byte array we can use as the data in the POST message
    {

        // Build up the post message header

        var sb = new StringBuilder();



        //accepts a message parameter which will be the caption to go with the photo



        sb.Append(Prefix).Append(BoundaryString).Append(NewLine);

        //sb.Append("Content-Disposition: form-data; name="message"");

        sb.Append("Content-Disposition: form-data; name="apikey"");

        sb.Append(NewLine);

        sb.Append(NewLine);

        sb.Append(PhotoCaption);

        sb.Append(NewLine);



        //data for the image

        string filename = @"file.jpg";

        string contenttype = @"image/jpeg";



        sb.Append(Prefix).Append(BoundaryString).Append(NewLine);

        sb.Append("Content-Disposition: form-data; filename="").Append(filename).Append(""").Append(NewLine);

        sb.Append("Content-Type: ").Append(contenttype).Append(NewLine).Append(NewLine);



        byte[] ba_Header = Encoding.UTF8.GetBytes(sb.ToString());

        byte[] ba_photo = ImageToByteArray(PhotoToPost);

        byte[] ba_footer = Encoding.UTF8.GetBytes(String.Concat(NewLine, Prefix, BoundaryString, Prefix, NewLine));



        // Combine all the byte arrays into one - this is the data we will post

        byte[] postData = new byte[ba_Header.Length   ba_photo.Length   ba_footer.Length];

        Buffer.BlockCopy(ba_Header, 0, postData, 0, ba_Header.Length);

        Buffer.BlockCopy(ba_photo, 0, postData, ba_Header.Length, ba_photo.Length);

        Buffer.BlockCopy(ba_footer, 0, postData, ba_Header.Length   ba_photo.Length, ba_footer.Length);



        //Set the lastposteddata variable to we can show it

        ms_lastposteddata = ByteArrayToString(postData);



        //return the data as a byte array

        return postData;

    }



    private string ByteArrayToString(byte[] bytes)
    {

        //Converts the raw post data so you can display it for testing, etc...

        System.Text.Encoding enc = System.Text.Encoding.UTF8;

        string PostString = enc.GetString(bytes, 0, bytes.Length);

        return PostString;

    }



    private string ms_lastposteddata = "No Data Posted Yet";

    public string LastPostedData
    {

        get { return ms_lastposteddata; }

    }

    #endregion







    #region HTTPWebRequest

    //Posts the data to Facebook - can only post to me/photos (no access to users wall)



    public void PostPhotoHTTPWebRequest(byte[] postData)
    {

        try
        {

            //Fire up an HttpWebRequest and pass in the facebook url for posting as well as the AccessToken

            //The AccessToken has to be in the URL - it didn't work just passing it as part of the POST data
            Encoding objEnc = Encoding.UTF8;
            string boundary = @"0xKhTmLbOuNdArY";
            HttpWebRequest request = HttpWebRequest.Create("http://app.myweb.com/api/v1/poster/post/photo/file") as HttpWebRequest;
            request.Method = "POST";
            request.ContentType = string.Format("multipart/form-data;charset=utf-8; boundary={0}", boundary);
            StringBuilder sb = new StringBuilder();
            sb.AppendFormat("--{0}rn", boundary);
            sb.AppendFormat("Content-Disposition: form-data; name="apikey"rnrn");
            sb.AppendLine(ms_caption);
            sb.AppendFormat("--{0}rn", boundary);
            sb.AppendFormat("Content-Disposition: form-data; name="photoFile"; filename=""   "file.jpg"   """   "rn");
            sb.AppendFormat("Content-Type:image/jpegrnrn");
            byte[] req_before_img = objEnc.GetBytes(sb.ToString());
            byte[] req_img = postData;
            String strFooter = String.Format("--{0}--", boundary);
            byte[] req_after_img = objEnc.GetBytes(strFooter);

            byte[] data_to_send = new byte[req_before_img.Length   req_img.Length   req_after_img.Length];

            // byte[] data_to_send;
            Buffer.BlockCopy(req_before_img, 0, data_to_send, 0, req_before_img.Length);
            Buffer.BlockCopy(req_img, 0, data_to_send, req_before_img.Length, req_img.Length);
            Buffer.BlockCopy(req_after_img, 0, data_to_send, req_before_img.Length   req_img.Length, req_after_img.Length);
            request.BeginGetRequestStream((ar) => { GetRequestStreamCallback(ar, data_to_send); }, request);

            /******************************************************************************************************/

            /******************************************************************************************************/
        }

        catch (Exception ex)
        {

            MessageBox.Show(ex.ToString());

        }

    }



    private void GetRequestStreamCallback(IAsyncResult asynchronousResult, byte[] postData)
    {

        try
        {

            HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;



            // End the operation

            Stream postStream = request.EndGetRequestStream(asynchronousResult);



            // Write to the request stream.

            postStream.Write(postData, 0, postData.Length);

            postStream.Close();



            // Start the asynchronous operation to get the response

            request.BeginGetResponse(new AsyncCallback(GetResponseCallback), request);



        }

        catch (Exception ex)
        {

            Deployment.Current.Dispatcher.BeginInvoke(() => { UpdatePostStatus("Error Uploading [GetRequestStreamCallback]:", ex.ToString()); });

        }

    }



    private void GetResponseCallback(IAsyncResult asynchronousResult)//i get the exception notSupportedException
    {

        try
        {

            HttpWebRequest request = (HttpWebRequest)asynchronousResult.AsyncState;



            // End the operation

            HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(asynchronousResult);

            Stream streamResponse = response.GetResponseStream();

            StreamReader streamRead = new StreamReader(streamResponse);

            string responseString = streamRead.ReadToEnd();


            //$$$$$$$$$$
            Dictionary<string, string> Items = new Dictionary<string, string>();
            Items = JsonConvert.DeserializeObject<Dictionary<string, string>>(responseString);
            bool bFlag = false;
            foreach (KeyValuePair<string, string> kvp in Items)
            {
                String strKey = kvp.Key;
                if (strKey == "photoUrl")
                {
                    responseString = kvp.Value;
                    bFlag = true;
                }

            }

            if (!bFlag)
            {
                (Application.Current as App).objTwitterPostMessageContainer.properties = "error";
            }

            else
            {
                (Application.Current as App).objTwitterPostMessageContainer.properties = "{"imageToUpload":"   """   responseString   ""}";
            }
            //$$$$$$$$$$
            System.Diagnostics.Debug.WriteLine(responseString);

            //Update the UI



            Deployment.Current.Dispatcher.BeginInvoke(() => { UpdatePostStatus("Upload Success! Picture ID:", responseString); });



            // Close the stream object

            streamResponse.Close();

            streamRead.Close();

            // Release the HttpWebResponse

            response.Close();



        }

        catch (Exception ex)
        {

            //MessageBox.Show(ex.ToString());

            Deployment.Current.Dispatcher.BeginInvoke(() => { UpdatePostStatus("Error Uploading [GetResponseCallback]:", ex.ToString()); });

        }

    }

    #endregion



    #region ImageManipulation

    public BitmapImage GetImageFromIsolatedStorage(String ImageFileName)

    //Opens an image file in isolated storage and returns it as a

    //BitmapImage object we could use as the image in the PostData method
    {

        {

            using (IsolatedStorageFile isf = IsolatedStorageFile.GetUserStoreForApplication())
            {

                // Open the file

                using (IsolatedStorageFileStream isfs = isf.OpenFile(ImageFileName, FileMode.Open, FileAccess.Read))
                {

                    //use the stream as the source of the Bitmap Image

                    BitmapImage bmpimg = new BitmapImage();

                    bmpimg.SetSource(isfs);

                    isfs.Close();

                    return bmpimg;

                }

            }

        }

    }





    private byte[] ImageToByteArray(BitmapImage bm_Image)

    //ImageToByteArray(BitmapImage) accepts a BitmapImage object and

    //converts it to a byte array we can use in the POST buffer
    {

        byte[] data;

        {

            // Get an Image Stream

            MemoryStream ms_Image = new MemoryStream();



            // write an image into the stream

            // System.Windows.Media.Imaging.Extensions.SaveJpeg(new WriteableBitmap(bm_Image), ms_Image, bm_Image.PixelWidth, bm_Image.PixelHeight, 0, 100);


            System.Windows.Media.Imaging.Extensions.SaveJpeg(new WriteableBitmap(bm_Image), ms_Image, 320, 320, 0, 100);


            // reset the stream pointer to the beginning

            ms_Image.Seek(0, 0);

            //read the stream into a byte array

            data = new byte[ms_Image.Length];

            ms_Image.Read(data, 0, data.Length);

            ms_Image.Close();

        }

        //data now holds the bytes of the image

        return data;

    }





    public BitmapImage GetBitmapImageFromUIElement(UIElement element)

    //GetBitmapImageFromUIElement accepts a UIElement (canvas, grid, image, etc...)

    //and builds a BitmapImage of it including any child elements
    {

        try
        {

            WriteableBitmap bmp = new WriteableBitmap((int)element.RenderSize.Width, (int)element.RenderSize.Height);

            bmp.Render(element, null);

            bmp.Invalidate();



            // Get an Image Stream

            MemoryStream ms_Image = new MemoryStream();



            // write the image into the stream

            bmp.SaveJpeg(ms_Image, (int)element.RenderSize.Width, (int)element.RenderSize.Height, 0, 100);

            // reset the stream pointer to the beginning

            ms_Image.Seek(0, 0);

            //use the stream as the source of the Bitmap Image

            BitmapImage bmpimg = new BitmapImage();

            bmpimg.SetSource(ms_Image);

            ms_Image.Close();



            return bmpimg;

        }

        catch (Exception ex)
        {

            UpdatePostStatus("Error Getting Bitmap from UIElement:", ex.Message);

            return null;

        }

    }

    #endregion



    #region Events code



    //Raise the PostStatus Event so the calling code knows whats going on

    private void UpdatePostStatus(string strHeader, string strContents)
    {

        if (PostStatus != null)
        {

            PostStatus(this, new PostStatusEventArgs(strHeader, strContents));

        }

    }

    public class PostStatusEventArgs : EventArgs
    {

        private readonly string msg_header = string.Empty;

        private readonly string msg_contents = string.Empty;

        // Constructor.



        public PostStatusEventArgs(string msgHeader, string msgContents)
        {

            this.msg_header = msgHeader;

            this.msg_contents = msgContents;

        }



        // Properties.

        public string MessageHeader { get { return msg_header; } }

        public string MessageContents { get { return msg_contents; } }

    }
    //the PostStatus Event sends status updates

    public delegate void PostStatusEventHandler(object sender,PostStatusEventArgs e);

    public event PostStatusEventHandler PostStatus;

    #endregion
}
  

Комментарии:

1. Какое сообщение об ошибке InvalidOperationException? Если ошибка действительно возникает в SetSource строке, вы можете удалить ImageUploader код из своего вопроса, поскольку он не использовался при возникновении исключения.

2. в uploadPhoto (objBitmapImage) появляется сообщение об ошибке «Эта операция не поддерживается в относительном URI»

3. В вашем примере кода говорится, что исключение возникает для objBitmapImage . Установить исходную строку. Это там или в методе uploadPhoto?

4. да, исключение возникает в objBitmapImage. Установить исходную строку. я получаю uriSourse как null ({}).

5. Этот код работает правильно в Windows phone 7. после обновления до 7.1 я столкнулся с этой проблемой. Проблема связана с обновлением до версии 7.1? что вы думаете?

Ответ №1:

PhotoChooserTask.Завершенный вызывается независимо от того, была выбрана фотография или нет. Вы должны проверять свойство TaskResult PhotoResult и загружать фотографию только в том случае, если значение равно TaskResult.OK

Ваша проблема с совместимостью может быть связана с быстрым переключением приложений. Попробуйте запустить приложение в эмуляторе с включенным надгробием ( Project Properties :: Debug ) и посмотрите, не возникает ли проблема.

Комментарии:

1. Проблема все еще возникает .. но если я изменю код objBitmapImage. setSource(например,ChosenPhoto); в objBitmapImage . UriSource = (новый Uri(например,OriginalFileName)); проблема решена, но при записи изображения в поток байтов возникает исключение недопустимого указателя. мой код для преобразования в байтовый массив приведен ниже

2. private byte[] ImageToByteArray(BitmapImage bm_Image) //ImageToByteArray(BitmapImage) принимает объект BitmapImage и // преобразует его в массив байтов, который мы можем использовать в буфере POST { byte[] data=null; { MemoryStream ms_Image = new MemoryStream(); System. Windows. Медиафайлы. Создание образа. Расширения. SaveJpeg(new WriteableBitmap(bm_Image), ms_Image, 320, 320, 0, 100); ms_Image. Поиск (0, 0); данные = новый байт[ms_Image. Длина]; ms_Image. Чтение (данные, 0, данные. Длина); ms_Image. Close(); } //данные теперь содержат байты возвращаемых данных изображения; }

3. Вы не можете использовать OriginalFileName для доступа к файлу, только ChosenPhoto . Вы пробовали включить надгробие в меню отладки?

4. Я не обновляю свой проект до wp7.1, только ОС телефона и emulator.in окно свойств я изменил конфигурацию на debug достаточно ли этого?

5. Если вы изменили «Версию Windows Phone» в окне свойств на «7.1», то вы обновили свой проект до 7.1