#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