I am trying to download and save Zip file from server.
I have string from server.
lastStatusCode = response.StatusCode;
using (StreamReader httpWebStreamReader = new StreamReader(response.GetResponseStream()))
{
string result = httpWebStreamReader.ReadToEnd();
RequestList[0].OnResponse(result, lastStatusCode);
}
if "lastStatusCode" is OK then i am making Zip file.
public async void saveFile(string response)
{
var fileBytes = System.Text.Encoding.UTF8.GetBytes(response.ToCharArray());
// Get the local folder.
StorageFolder local = Windows.Storage.ApplicationData.Current.LocalFolder;
// Create a new folder name MyFolder.
var dataFolder = await local.CreateFolderAsync("TestFolder",
CreationCollisionOption.OpenIfExists);
// Create a new file named DataFile.txt.
var file = await dataFolder.CreateFileAsync("File.zip",
CreationCollisionOption.ReplaceExisting);
// Write the data from the textbox.
using (var s = await file.OpenStreamForWriteAsync())
{
s.Write(fileBytes, 0, fileBytes.Length);
}
}
what I am doing wrong? I can't open this file.
I fixed that problem! Converting Stream to String and then String to Byte was bad idea.
I was converting Stream to byte:
lock (RequestList)
{
//WebRequest request = (WebRequest)callbackResult.AsyncState;
HttpWebRequest request = (HttpWebRequest)callbackResult.AsyncState;
try
{
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(callbackResult);
Stream s = response.GetResponseStream();
lastStatusCode = response.StatusCode;
s.Position = 0;
// Now read s into a byte buffer with a little padding.
byte[] bytes = new byte[s.Length];
int numBytesToRead = (int)s.Length;
int numBytesRead = 0;
do
{
// Read may return anything from 0 to 10.
int n = s.Read(bytes, numBytesRead, numBytesToRead);
numBytesRead += n;
numBytesToRead -= n;
} while (numBytesToRead > 0);
s.Close();
WriteFile("Test.zip",bytes);
RequestList[0].OnResponse(bytes, lastStatusCode);
}
catch (WebException e)
{
Debug.WriteLine("Error : " + e.Message);
byte[] streamData = System.Text.Encoding.UTF8.GetBytes(e.Message);
RequestList[0].OnResponse(streamData, HttpStatusCode.InternalServerError);
}
}
I am making zip file here
public async void WriteFile(string fileName, byte[] response)
{
IStorageFolder applicationFolder = ApplicationData.Current.LocalFolder;
IStorageFile storageFile = await applicationFolder.CreateFileAsync(fileName, CreationCollisionOption.ReplaceExisting);
//var content = System.Text.Encoding.UTF8.GetBytes(response);
using (Stream stream = await storageFile.OpenStreamForWriteAsync())
{
await stream.WriteAsync(response, 0, response.Length);
}
}
Related
I want to read file using StreamResourceInfo GetResourceStream(Uri uriResource) method where my filename is Assets and its type if file (extension) so I used following line of code in windows phone 8.1 sdk,
StreamResourceInfo info = App.GetResourceStream(new Uri("Assets", UriKind.Relative));
But the info variable shows null value.
Is it necessary to use GetResourceStream in your case? Your question is a little bit unclear, but if you want to get the content of the file you can try this:
public async Task<string> GetFileContent(string fileName)
{
try
{
string text = string.Empty;
StorageFile storageFile = await Windows.ApplicationModel.Package.Current.InstalledLocation.GetFileAsync(fileName);
if (storageFile != null)
{
IBuffer buffer = await FileIO.ReadBufferAsync(storageFile);
DataReader reader = DataReader.FromBuffer(buffer);
byte[] fileContent = new byte[reader.UnconsumedBufferLength];
reader.ReadBytes(fileContent);
text = Encoding.UTF8.GetString(fileContent, 0, fileContent.Length);
}
return text;
}
catch (Exception e)
{
return string.Empty;
}
}
Note, it returns string UTF8 encoded, you can change it if necessary.
usage:
var fileContent = await GetFileContent(#"Assets\[yourfile]");
My request need to look like this:
Content-Type: multipart/form-data; boundary=---BOUNDARY
-----BOUNDARY
name="receipt_photo"; filename="image_filename.jpg"
Content-Type: image/jpeg
-----BOUNDARY
I am trying to send it using following code
public async static Task addPhotosToReceipt(BitmapImage image, int idReceipt)
{
User user = PhoneApplicationService.Current.State["user"] as User;
if (user.customer.token != null)
{
RestConnector rc = new RestConnector();
byte[] data;
try
{
using (MemoryStream ms = new MemoryStream())
{
WriteableBitmap btmMap = new WriteableBitmap(image);
System.Windows.Media.Imaging.Extensions.SaveJpeg(btmMap, ms, image.PixelWidth, image.PixelHeight, 0, 100);
data = ms.ToArray();
}
string response = await rc.postAsyncData("/api/v1/receipts/" + idReceipt + "/receipt_photos/?token=" + user.customer.token, data);
if (response.Contains("error"))
{
MessageBox.Show(response);
}
}
catch (Exception ex)
{
}
}
}
//in RestConnector class
public async Task<string> postAsyncData(string adress, byte[] file)
{
using (var client = new HttpClient())
{
using (var content = new MultipartFormDataContent("---BOUNDARY"))
{
content.Add(new StringContent("-----BOUNDARY\nname=\"receipt_photo\"; filename=\"image_filename.jpg\"\nContent-Type: image/jpeg\n-----BOUNDARY"));
content.Add(new StreamContent(new MemoryStream(file)));
using (var message = await client.PostAsync(basicUrl + adress, content))
{
var input = await message.Content.ReadAsStringAsync();
return input;
}
}
}
}
In response I should get URL's to uploaded photos, but instead I got URL's to default photos. I think there is something with my request because on android it works fine.
Maybe I choosed wrong way to create byte from my bitmap?
I am reading data from IsolatedStorage, but can't edit it in ScheduledTask. How can I edit it?
private void StartToastTask(ScheduledTask task)
{
long rank = 0, difference = 0;
string text = "", nickname = "";
PishtiWCF.PishtiWCFServiceClient ws = ServiceClass.GetPishtiWCFSvc();
ws.GetUsersRankCompleted += (src, e) =>
{
try
{
if (e.Error == null)
{
difference = rank - e.Result.GeneralRank;
if (!String.IsNullOrEmpty(nickname))
{
if (difference < 0)
text = string.Format("{0}, {1} kişi seni geçti!", nickname, difference.ToString(), e.Result.GeneralRank);
else if (difference > 0)
text = string.Format("{0}, {1} kişiyi daha geçtin!", nickname, Math.Abs(difference).ToString(), e.Result.GeneralRank);
else if (e.Result.GeneralRank != 1)
text = string.Format("{0}, sıralamadaki yerin değişmedi!", nickname, e.Result.GeneralRank);
else
text = string.Format("{0}, en büyük sensin, böyle devam!", nickname);
}
else
return;
Mutex mut;
if (!Mutex.TryOpenExisting("IsoStorageMutex", out mut))
mut = new Mutex(false, "IsoStorageMutex");
mut.WaitOne();
using (IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream stream = file.OpenFile("UserRanks", FileMode.Open, FileAccess.Write))
{
StreamWriter writer = new StreamWriter(stream);
writer.Write(string.Format("{0},{1}", nickname, e.Result.GeneralRank));
writer.Close();
stream.Close();
}
}
mut.ReleaseMutex();
ShellToast toast = new ShellToast();
toast.Title = "Pishti";
toast.Content = text;
toast.Show();
}
FinishTask(task);
}
catch (Exception)
{
}
};
try
{
Mutex mut;
if (!Mutex.TryOpenExisting("IsoStorageMutex", out mut))
mut = new Mutex(false, "IsoStorageMutex");
mut.WaitOne();
using (IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForApplication())
{
using (IsolatedStorageFileStream stream = file.OpenFile("UserRanks", FileMode.Open, FileAccess.Read))
{
using (StreamReader reader = new StreamReader(stream))
{
string temp = reader.ReadToEnd();
if (temp.Split(',').Count() > 1)
{
nickname = temp.Split(',')[0];
rank = long.Parse(temp.Split(',')[1]);
ws.GetUsersRankAsync(nickname);
}
reader.Close();
}
stream.Close();
}
}
mut.ReleaseMutex();
}
catch (Exception)
{
}
}
I am getting rank from UserRanks file, for example 1200, but when I get and data from WCF, edit it to 1000 and want to write it to IsolatedStorage, It doesn't crash application but it fails.
Do you know why?
Thanks.
I've fixed it with delete file.
Mutex mut;
if (!Mutex.TryOpenExisting("IsoStorageMutex", out mut))
mut = new Mutex(false, "IsoStorageMutex");
mut.WaitOne();
using (IsolatedStorageFile file = IsolatedStorageFile.GetUserStoreForApplication())
{
if (file.FileExists("UserRanks"))
file.DeleteFile("UserRanks");
using (IsolatedStorageFileStream stream = file.OpenFile("UserRanks", FileMode.OpenOrCreate, FileAccess.Write))
{
StreamWriter writer = new StreamWriter(stream);
writer.Write(string.Format("{0},{1}", nickname, e.Result.GeneralRank));
writer.Close();
stream.Close();
}
}
mut.ReleaseMutex();
You appear to write to the file first, which makes sense, but when you do so you use a file access mode - FileMode.Open - which means "open an existing file". The first time you do this the file won't exist and the open will fail.
You should either use FileMode.OpenOrCreate, which is self explanatory, or FileMode.Append which will open the file if it exists and seek to the end of the file, or create a new file if it doesn't.
If you want to throw away any pre-existing file (which is what your delete then create will do) then just use FileMode.Create
I am building a WP8 app that downloads images using HttpClient in a background task. My problem is that some images are not downloaded no matter how much time I wait for them to finish. The image sizes are a few megabytes at maximum.
The code I use to download images:
internal static async Task<bool> Download_Wallpaper(string image_url, string file_name, string destination_folder_name)
{
try
{
using (var client = new HttpClient())
{
// 12MB max images
client.Timeout = TimeSpan.FromSeconds(5);
client.MaxResponseContentBufferSize = DeviceStatus.ApplicationMemoryUsageLimit / 2;
//client.Timeout = TimeSpan.FromSeconds(5);
byte[] image_byte_arr;
try
{
/* var requestMessage = new HttpRequestMessage( HttpMethod.Get, image_url );
var responseMessage = await client.SendAsync((requestMessage));
// byte array of image
image_byte_arr = await responseMessage.Content.ReadAsByteArrayAsync();
*/
// byte array of image
image_byte_arr = await client.GetByteArrayAsync(image_url);
}
// Could not download
catch (OutOfMemoryException X)
{
GC.Collect();
return false;
}
var folder = await StorageFolder.GetFolderFromPathAsync(destination_folder_name);
// Create file
StorageFile file = await folder.CreateFileAsync(file_name, CreationCollisionOption.ReplaceExisting);
using (var write_stream = await file.OpenStreamForWriteAsync())
{
write_stream.Write(image_byte_arr, 0, image_byte_arr.Length);
}
Console.WriteLine(DeviceStatus.ApplicationCurrentMemoryUsage);
return true;
}
}
catch (HttpRequestException X)
{
Console.WriteLine(X);
return false;
}
catch (OutOfMemoryException X)
{
GC.Collect();
return false;
}
catch (Exception X)
{
Console.WriteLine(X);
return false;
}
}
This is an example image that fails to download: https://upload.wikimedia.org/wikipedia/commons/9/95/Tracy_Caldwell_Dyson_in_Cupola_ISS.jpg
In my experience all wikimedia images fail to download for some reason.
I see no way of tracking download progress using HttpClient. Is there a way to do so?
Edit: It seems that setting the timeout does not have any function. The HttpRequestException is not thrown after 5 seconds.
Edit2: I tried a different approach, the one that anonshankar suggested. With that method the code would get stuck at the line:
byte[] img = response.Content.ReadAsByteArrayAsync();
So the HttpResponse arrives, but somehow the bytes could not be read out, no matter how much time I gave it. How could this even happen? The hard part is getting the response, reading out the bytes should be simple.
Again, this only happens with some images, most of them downloads correctly. One example is mentioned above.
I have modified my image downloader code, so that it times out after a few seconds. Here is my final code:
internal static async Task<bool> Download_Wallpaper(string image_url, string file_name, string destination_folder_name)
{
try
{
using (var client = new HttpClient())
{
// prevent running out of memory
client.MaxResponseContentBufferSize = DeviceStatus.ApplicationMemoryUsageLimit / 3;
byte[] image_byte_arr = null;
using (CancellationTokenSource cts = new CancellationTokenSource())
{
var task = Task.Factory.StartNew(() =>
{
try
{
image_byte_arr = client.GetByteArrayAsync(image_url).Result;
}
catch (AggregateException X)// Handling read errors, usually image is too big
{
Console.WriteLine(X.Message);
foreach (var v in X.InnerExceptions)
Console.WriteLine(v.Message);
image_byte_arr = null;
}
}, cts.Token);
bool finished_in_time = task.Wait(TimeSpan.FromSeconds(5));
if (!finished_in_time)// Timeout
{
cts.Cancel();
task.Wait();
return false;
}
else if (image_byte_arr == null)// Read error
{
return false;
}
}
var folder = await StorageFolder.GetFolderFromPathAsync(destination_folder_name);
// Create file
StorageFile file = await folder.CreateFileAsync(file_name, CreationCollisionOption.ReplaceExisting);
using (var write_stream = await file.OpenStreamForWriteAsync())
{
write_stream.Write(image_byte_arr, 0, image_byte_arr.Length);
}
Console.WriteLine(DeviceStatus.ApplicationCurrentMemoryUsage);
return true;
}
}
catch (HttpRequestException X)
{
Console.WriteLine(X);
return false;
}
catch (OutOfMemoryException X)
{
GC.Collect();
return false;
}
catch (Exception X)
{
Console.WriteLine(X);
return false;
}
}
Any improvement suggestions are welcome, and I still don't understand why does the method HttpContent.ReadAsByteArrayAsync() gets stuck.
Just try out this snippet which worked for me.
HttpClient client = new HttpClient();
HttpResponseMessage response = await client.GetAsync("give the url");
byte[] img = response.Content.ReadAsByteArray();
InMemoryRandomAccessStream randomAccessStream = new InMemoryRandomAccessStream();
DataWriter writer = new DataWriter(randomAccessStream.GetOutputStreamAt(0));
writer.WriteBytes(img);
await writer.StoreAsync();
BitmapImage b = new BitmapImage();
b.SetSource(randomAccessStream);
pic.Source = b; //(pic is an `<Image>` defined in the `XAML`
Hope it helps!
I have the following, and it uploads without errors, but the image is always 0 bytes.
Windows Phone App (this is called after selecting or taking a photo):
private void AddImage(PhotoResult e)
{
if (e.TaskResult == TaskResult.OK)
{
string serviceUri = Globals.GreedURL + #"API/UploadPhoto/test5.jpg";
HttpWebRequest request = (HttpWebRequest)HttpWebRequest.Create(serviceUri);
request.Method = "POST";
request.BeginGetRequestStream(result =>
{
Stream requestStream = request.EndGetRequestStream(result);
e.ChosenPhoto.CopyTo(requestStream);
requestStream.Close();
request.BeginGetResponse(result2 =>
{
try
{
HttpWebResponse response = (HttpWebResponse)request.EndGetResponse(result2);
if (response.StatusCode == HttpStatusCode.Created)
{
this.Dispatcher.BeginInvoke(() =>
{
MessageBox.Show("Upload completed.");
});
}
else
{
this.Dispatcher.BeginInvoke(() =>
{
MessageBox.Show("An error occured during uploading. Please try again later.");
});
}
}
catch
{
this.Dispatcher.BeginInvoke(() =>
{
MessageBox.Show("An error occured during uploading. Please try again later.");
});
}
e.ChosenPhoto.Close();
}, null);
}, null);
}
And here is the Web API:
public class UploadPhotoController : ApiController
{
public HttpResponseMessage Post([FromUri]string filename)
{
var task = this.Request.Content.ReadAsStreamAsync();
task.Wait();
Stream requestStream = task.Result;
// Retrieve storage account from connection string.
CloudStorageAccount storageAccount = CloudStorageAccount.Parse(ConfigurationManager.ConnectionStrings["StorageConnectionString"].ConnectionString);
// Create the blob client.
CloudBlobClient blobClient = storageAccount.CreateCloudBlobClient();
// Retrieve reference to a previously created container.
CloudBlobContainer container = blobClient.GetContainerReference("profilepics");
container.CreateIfNotExists();
var permissions = container.GetPermissions();
permissions.PublicAccess = BlobContainerPublicAccessType.Blob;
container.SetPermissions(permissions);
string uniqueBlobName = string.Format("test.jpg");
CloudBlockBlob blob = container.GetBlockBlobReference(uniqueBlobName);
blob.Properties.ContentType = "image\\jpeg";
blob.UploadFromStream(task.Result);
HttpResponseMessage response = new HttpResponseMessage();
response.StatusCode = HttpStatusCode.Created;
return response;
}
}
Any ideas?
Any help would be appreciated.