How to send an image from Android to a WCF server? - c#

I working on sending an image from Android to a WCF server. I tried sending the FileBOdy in a multi-part body, but that didn't get the job done. Finally I tried sending a ByteArrayBody in a multi-part body. It did work, but I got a corrupted image in server. I googled a lot, but couldn't get an acceptable solution to my problem. Can any one spot a mistake in my Android or WCF code?
Android code
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bitmap.compress(CompressFormat.JPEG, 75, bos);
byte[] data = bos.toByteArray();
// Making HTTP request
try {
// defaultHttpClient
DefaultHttpClient httpClient = new DefaultHttpClient();
String URL1 = "http://rohit-pc:8078/service1.svc/UploadImage";
HttpPost httpPost = new HttpPost(URL1);
ContentBody bin = null;
MultipartEntity reqEntity = new MultipartEntity(
HttpMultipartMode.BROWSER_COMPATIBLE);
ByteArrayBody bab = new ByteArrayBody(data, "forest.jpg");
reqEntity.addPart("image", bab);
reqEntity.addPart("photoCaption", new StringBody("sfsdfsdf"));
httpPost.setEntity(reqEntity);
HttpResponse response = httpClient.execute(httpPost);
BufferedReader reader = new BufferedReader(new InputStreamReader(
response.getEntity().getContent(), "UTF-8"));
String sResponse;
s = new StringBuilder();
while ((sResponse = reader.readLine()) != null) {
s = s.append(sResponse);
}
System.out.println("Response: " + s);
} catch (Exception e) {
Log.e(e.getClass().getName(), e.getMessage());
}
WCF code
public string GetStream(Stream str,string filename) {
Guid guid = Guid.NewGuid();
string Path = System.Web.Hosting.HostingEnvironment.MapPath("~/Images");
FileStream file = new FileStream(Path + "/" +filename, FileMode.Create);
byte[] bytearray = new byte[100000000];
int bytesRead, totalBytesRead = 0;
do {
bytesRead = str.Read(bytearray, 0, bytearray.Length);
totalBytesRead += bytesRead;
} while (bytesRead > 0);
file.Write(bytearray, 0, bytearray.Length);
file.Close();
file.Dispose();
return "Success";
}

I would say use Base64 format to send the image encoded in base64 format as string.

Sorry to answer an old question. But I had spent over 5 hours to figure out the issue. So would like to share the solution I found. My issue was a corrupted image saved in the server.
Actually, WCF does not have an effective way of parsing the multipart form data. Thats why the suggestion from MS is to use the raw stream to transmit images to wcf services.
So after a few hours of struggling to get rid of MultipartEntity(replaced with ByteArrayEntity), I finally got it working by using the below code. Hope this should help some one.
Android
Bitmap bm = BitmapFactory.decodeFile(params[0]);
ByteArrayOutputStream bos = new ByteArrayOutputStream();
bm.compress(CompressFormat.JPEG, 75, bos);
byte[] data = bos.toByteArray();
// the below is the important one, notice no multipart here just the raw image data
request.setEntity(new ByteArrayEntity(data));
then the rest of the actual http client continues.
Wcf Interface
<OperationContract()>
<WebInvoke(Method:="POST",
ResponseFormat:=WebMessageFormat.Json,
BodyStyle:=WebMessageBodyStyle.Bare,
UriTemplate:="/UploadPhoto?UsedCarID={UsedCarID}&FileName={FileName}")>
Sub UploadPhoto(UsedCarID As Integer, FileName As String, FileContents As Stream)
This is my first post at Stack Overflow thank you so much.

Related

Same Image, but different base64 string in Azure Web app and local machine

I have a very strange issue. I am converting Image to base64string in an asp.net web API hosted in Azure app service and getting the wrong image string.
If I run the code in the local machine I am getting the correct value.
public static string GetImageFromSharePointOnline(string imageUrl)
{
try
{
using (var clientContext = CreateContext(URL))
{
clientContext.ExecutingWebRequest += ExecutingWebRequest;
FileInformation fileInformation = null;
Stream returnStream = new MemoryStream();
int readCount;
var buffer = new byte[8192];
Uri image = new Uri(imageUrl);
try
{
fileInformation = Microsoft.SharePoint.Client.File.OpenBinaryDirect(clientContext, image.AbsolutePath);
while ((readCount = fileInformation.Stream.Read(buffer, 0, buffer.Length)) != 0)
{
returnStream.Write(buffer, 0, readCount);
}
}
catch (Exception ex) { }
returnStream.Seek(0, SeekOrigin.Begin);
return "data:image/" + GetFileExtensionFromUrl(imageUrl) + ";base64," + Convert.ToBase64String(buffer);
// return Convert.ToBase64String(buffer);
}
}
catch (Exception ex) { }
}
Azure web api output:
data:image/jpg;base64,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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=
output from my local machine:
data:image/jpg;base64,/9j/4AAQSkZJRgABAgAAZABkAAD/7AARRHVja3kAAQAEAAAAPAAA/+EEJWh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8APD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZXRhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS42LWMxNDAgNzkuMTYwNDUxLCAyMDE3LzA1LzA2LTAxOjA4OjIxICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucyMiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtbG5zOnhtcD0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wLyIgeG1sbnM6ZGM9Imh0dHA6Ly9wdXJsLm9yZy9kYy9lbGVtZW50cy8xLjEvIiB4bXBNTTpPcmlnaW5hbERvY3VtZW50SUQ9InV1aWQ6NUQyMDg5MjQ5M0JGREIxMTkxNEE4NTkwRDMxNTA4QzgiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6OEVDOEIyODRENDcxMTFFN0IwODdFNDUxRTNDRTEzQ0IiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6OEVDOEIyODNENDcxMTFFN0IwODdFNDUxRTNDRTEzQ0IiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgSWxsdXN0cmF0b3IgQ1M2IChXaW5kb3dzKSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOkQ3QjM5QkJCOTFBOUU3MTFBNEE0RDlCRjU4RjAwQ0FGIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjdCNzYyMDk4ODdBOUU3MTFBQ0MwRDE2NUU0NzdENzFFIi8+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
Can anyone help me with this please.
You're initializing a MemoryStream:
Stream returnStream = new MemoryStream();
(should be var returnStream = new MemoryStream();)
as the container for the bytes read from a Stream.
The Image bytes are read from the source Stream using a buffer:
var buffer = new byte[8192];
which is ok for a NetworkStream.
Assuming Uri image = new Uri(imageUrl); represents the same object in both environments, you the read a [buffer] number of bytes (which is the maximum value, the actual bytes read may be less than that) and write the bytes read - the value is stored in the readCount variable - to the MemoryStream:
try
{
fileInformation = Microsoft.SharePoint.Client.File.OpenBinaryDirect(clientContext, image.AbsolutePath);
while ((readCount = fileInformation.Stream.Read(buffer, 0, buffer.Length)) != 0)
{
returnStream.Write(buffer, 0, readCount);
}
}
When the source Stream is read to end, the MemoryStream contains the Image bytes.
At this point, you want to convert the Image bytes to a Base64String.
Of course, you need to convert the content of your MemoryStream, returnStream, not the buffer content, which is only used as a temporary container for the bytes coming from the source Stream. So just change:
Convert.ToBase64String(buffer);
to:
Convert.ToBase64String(returnStream.ToArray());
Setting returnStream.Position = 0 before calling returnStream.ToArray() is not necessary in this context, but it doesn't hurt either.
Side note: those empty catch blocks don't serve you well. Either add logging features or remove.

Amazon S3 File Full of Zeros

I'm downloading a PDF file from an AWS S3 bucket using the official client in C#. It appears to download the whole file, but everything is 0s after 8192 (0x2000) bytes.
See below (original file on left, S3 download on right):
Any ideas as to why this is happening would be greatly appreciated.
Here's the code:
var client = new AmazonS3Client(
new AmazonS3Config
{
RegionEndpoint = RegionEndpoint.EUWest1
});
var transferUtility = new TransferUtility(client);
var request = new TransferUtilityOpenStreamRequest
{
BucketName = bucketName,
Key = key
};
using (var stream = transferUtility.OpenStream(request))
{
var bytes = new byte[stream.Length];
stream.Read(bytes, 0, (int)stream.Length);
stream.Close();
return bytes;
}
Thanks in advance,
Steve.
For anyone else hitting this issue, it was a case of having to repeatedly call Read on the stream until all bytes have been received:
using (var stream = transferUtility.OpenStream(request))
{
var position = 0;
var length = stream.Length;
var bytes = new byte[length];
do
{
position += stream.Read(bytes, position, (int)(stream.Length - position));
} while (position < length);
stream.Close();
return bytes;
}
Thanks to John for pointing that out.
Edit:
Or check out this extension method kindly pointed out by JohnLBevan: https://stackoverflow.com/a/24412022/361842

Sending and receiving images via a socket

I have a C# desktop app. It connects to another PC on my network which is a UWP C# app.
I am trying to send an image or 2 to my listening socket and to test this I get the listening socket to send me the image back.
The trouble is that even though my server recieves all the bytes that were orginally sent the recieved image back to the client is not of the same size.
To make this even more weird is sometimes the returned bytes are correct and I get the whole image and when I attempt to send 2 images the 1st one is OK and the 2nd one is not.
Then it will/can revert back to no images being sent back correctly.
I think is maybe to do with the async/await parts bit I am not sure how.
This is my server code:
using (IInputStream input = args.Socket.InputStream)
{
byte[] data = new byte[BufferSize];
IBuffer buffer = data.AsBuffer();
uint dataRead = BufferSize;
while (dataRead == BufferSize)
{
await input.ReadAsync(buffer, BufferSize, InputStreamOptions.Partial);
requestInBytes.AddRange(data.Take((int) buffer.Length));
dataRead = buffer.Length;
}
}
var ct = requestInBytes.Count;
I then trip out the header info:
int counter = 0;
counter = requestCommand[0].Length;
counter = counter + requestCommand[1].Length;
counter = counter + requestCommand[2].Length;
counter = counter + requestCommand[3].Length;
counter = counter + requestCommand[4].Length;
counter = counter + requestCommand[5].Length;
counter = counter + 6;
Now I extract the image:
var imgBody = new byte[totalBytes.Length- counter];
System.Buffer.BlockCopy(totalBytes, counter, imgBody, 0, imgBody.Length);
byteArray = imgBody;
And send just the image back:
using (IOutputStream output = args.Socket.OutputStream)
{
using (Stream response = output.AsStreamForWrite())
{
MemoryStream stream = new MemoryStream(byteArray);
await response.WriteAsync(byteArray, 0, byteArray.Length);
await response.FlushAsync();
}
}
This is my client code:
StringBuilder sb = new StringBuilder();
foreach (var gallery in Shared.CurrentJobGallery)
{
try
{
sb.Clear();
sb.Append(GeneralTags.ACTION_ADD);
sb.Append(Shared.DLE);
sb.Append("GALLERY");
sb.Append(Shared.DLE);
sb.Append(Shared.CurrentClientId);
sb.Append(Shared.DLE);
sb.Append(gallery.Title);
sb.Append(Shared.DLE);
sb.Append(gallery.Description);
sb.Append(Shared.DLE);
sb.Append(jobRef);
sb.Append(Shared.DLE);
byte[] galleryHdr = Encoding.UTF8.GetBytes(sb.ToString());
byte[] byteArray = new byte[galleryHdr.Length + gallery.ImageData.Length];
Buffer.BlockCopy(galleryHdr, 0, byteArray, 0, galleryHdr.Length);
Buffer.BlockCopy(gallery.ImageData, 0, byteArray, galleryHdr.Length, gallery.ImageData.Length);
List<byte> requestInBytes2 = new List<byte>();
System.Diagnostics.Debug.WriteLine("SENT: " + gallery.ImageData.Length.ToString());
using (TcpClient clientSocket = new TcpClient())
{
await clientSocket.ConnectAsync(GeneralTags.RASPBERRY_PI_IP_ADDRESS, GeneralTags.RASPBERRY_PI_PORT);
using (NetworkStream serverStream = clientSocket.GetStream())
{
List<byte> requestInBytes = new List<byte>();
serverStream.Write(byteArray, 0, byteArray.Length);
serverStream.Flush();
int i;
Byte[] bytes = new Byte[1024];
do
{
i = serverStream.Read(bytes, 0, bytes.Length);
byte[] receivedBuffer = new byte[i];
Array.Copy(bytes, receivedBuffer, i);
requestInBytes2.AddRange(receivedBuffer);
} while (serverStream.DataAvailable);
}
}
using (MemoryStream ms = new MemoryStream())
{
System.Diagnostics.Debug.WriteLine("BACK: " + requestInBytes2.Count.ToString());
ms.Write(requestInBytes2.ToArray(), 0, requestInBytes2.ToArray().Length);
Shared.ViewImage(Image.FromStream(ms, true));
}
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex.ToString());
}
}
Your problem is that TCP sockets are based around streams, not packets. It's true that "on the wire" everything is a packet, but when you're using TCP, you have no control over how the data is split up into packets or is reassembled into a stream.
In particular, this line of code is incorrect:
await input.ReadAsync(buffer, BufferSize, InputStreamOptions.Partial);
According to the docs, you must use the buffer returned from ReadAsync. Also note that this buffer may be a partial image, and it's up to your code to detect that situation, read more if necessary, and append those blocks together. Also, the buffer may contain part of one image and part of the next image; it's also up to your code to detect that and handle it correctly.
For this reason, most TCP applications use some form of message framing (described in more detail on my blog). Note that getting this right is surprisingly hard.
I strongly recommend that you use SignalR instead of raw TCP sockets. SignalR handles message framing for you, and it is capable of self-hosting (i.e., it does not require ASP.NET).

MemoryStream VS FileStream which one is better to use in Webservice for GZipStream decompress?

I have a asp.net webservice. some functionality of this webservice is to decompress clients request first. for this i have wrote 2 methods one uses MemoryStream and other uses FileStream.
When using MemoryStream sometiomes it get OutofMemoryException. so i have planned to use FileStream instead of MemoryStream for this reason.
before using this i just need a clarification that i am doing the right
thing for the right job.
N:B: Sometiome my clients will send 10MB+ data to the webservice which i need to decompress in webservice side. i have more then 200 clients running. and where the webservice is hosted there are more then 30 web application and webservice also hosted though my webservice is under different app pool.
I did see : GZIP decompression C# OutOfMemory
i get some knowledge from there but for webservice which one should better i have quite confusion based on my situation. and i need a clear understanding about this.
Decompress method (uses MemoryStream) is below:
public static string Decompress(string compressedText)
{
try
{
byte[] gzBuffer = Convert.FromBase64String(compressedText);
using (MemoryStream ms = new MemoryStream())
{
int msgLength = BitConverter.ToInt32(gzBuffer, 0);
ms.Write(gzBuffer, 4, gzBuffer.Length - 4);
byte[] buffer = new byte[msgLength];
ms.Position = 0;
using (GZipStream zip = new GZipStream(ms, CompressionMode.Decompress))
{
zip.Read(buffer, 0, buffer.Length);
}
return Encoding.UTF8.GetString(buffer);
}
}
catch (Exception ex)
{
DataSyncLog.Debug(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType + "::" + System.Reflection.MethodBase.GetCurrentMethod().ToString() + ":" + ex.ToString()+" : "+ex.StackTrace);
}
return string.Empty;
}
Decompress method (uses FileStream) is below:
public static string Decompress(string compressedText)
{
string SourceDirectory = System.Guid.NewGuid().ToString();
string DestinationDirectory = System.Guid.NewGuid().ToString();
try
{
File.WriteAllBytes(SourceDirectory, Convert.FromBase64String(compressedText));
using (FileStream fd = File.Create(DestinationDirectory))
{
using (FileStream fs = File.OpenRead(SourceDirectory))
{
fs.Seek(4, 0);
using (Stream csStream = new GZipStream(fs, CompressionMode.Decompress))
{
byte[] buffer = new byte[1024];
int nRead;
while ((nRead = csStream.Read(buffer, 0, buffer.Length)) > 0)
{
fd.Write(buffer, 0, nRead);
}
}
}
}
return Encoding.UTF8.GetString(File.ReadAllBytes(DestinationDirectory));
}
catch (Exception ex)
{
DataSyncLog.Debug(System.Reflection.MethodBase.GetCurrentMethod().DeclaringType + "::" + System.Reflection.MethodBase.GetCurrentMethod().ToString() + ":" + ex.ToString() + " : " + ex.StackTrace);
return string.Empty;
}
finally
{
ClearFiles(SourceDirectory);
ClearFiles(DestinationDirectory);
}
}
Someone could you please show me the right direction that which one
should i use or any modification needed to the method that uses
MemoryStream that can overcome this error. i will be grateful to you
if you give me a clear understanding about this or any code change
suggestion.
Working with stream looks more efficient memory-wise in the second case: with memory stream you hold entire stream in memory, with file stream you have only buffer of limited size.
Both of your methods can have problems with memory just because of their signature: when client sends 10MB this amount of memory will be allocated for compressedText argument and for return value.
You can look into changing interface of your service, so data is transfered in chunks (here you can find example of similar approach -http://www.codeproject.com/Articles/43272/Uploading-Large-Files-Through-Web-Service)
Or, if you can consider switching to WCF, it supports streaming transfer mode - http://msdn.microsoft.com/en-us/library/ms751463.aspx

Can't download complete image file from skydrive using REST API

I'm working on a quick wrapper for the skydrive API in C#, but running into issues with downloading a file. For the first part of the file, everything comes through fine, but then there start to be differences in the file and shortly thereafter everything becomes null. I'm fairly sure that it's just me not reading the stream correctly.
This is the code I'm using to download the file:
public const string ApiVersion = "v5.0";
public const string BaseUrl = "https://apis.live.net/" + ApiVersion + "/";
public SkyDriveFile DownloadFile(SkyDriveFile file)
{
string uri = BaseUrl + file.ID + "/content";
byte[] contents = GetResponse(uri);
file.Contents = contents;
return file;
}
public byte[] GetResponse(string url)
{
checkToken();
Uri requestUri = new Uri(url + "?access_token=" + HttpUtility.UrlEncode(token.AccessToken));
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(requestUri);
request.Method = WebRequestMethods.Http.Get;
WebResponse response = request.GetResponse();
Stream responseStream = response.GetResponseStream();
byte[] contents = new byte[response.ContentLength];
responseStream.Read(contents, 0, (int)response.ContentLength);
return contents;
}
This is the image file I'm trying to download
And this is the image I am getting
These two images lead me to believe that I'm not waiting for the response to finish coming through, because the content-length is the same as the size of the image I'm expecting, but I'm not sure how to make my code wait for the entire response to come through or even really if that's the approach I need to take.
Here's my test code in case it's helpful
[TestMethod]
public void CanUploadAndDownloadFile()
{
var api = GetApi();
SkyDriveFolder folder = api.CreateFolder(null, "TestFolder", "Test Folder");
SkyDriveFile file = api.UploadFile(folder, TestImageFile, "TestImage.png");
file = api.DownloadFile(file);
api.DeleteFolder(folder);
byte[] contents = new byte[new FileInfo(TestImageFile).Length];
using (FileStream fstream = new FileStream(TestImageFile, FileMode.Open))
{
fstream.Read(contents, 0, contents.Length);
}
using (FileStream fstream = new FileStream(TestImageFile + "2", FileMode.CreateNew))
{
fstream.Write(file.Contents, 0, file.Contents.Length);
}
Assert.AreEqual(contents.Length, file.Contents.Length);
bool sameData = true;
for (int i = 0; i < contents.Length && sameData; i++)
{
sameData = contents[i] == file.Contents[i];
}
Assert.IsTrue(sameData);
}
It fails at Assert.IsTrue(sameData);
This is because you don't check the return value of responseStream.Read(contents, 0, (int)response.ContentLength);. Read doesn't ensure that it will read response.ContentLength bytes. Instead it returns the number of bytes read. You can use a loop or stream.CopyTo there.
Something like this:
WebResponse response = request.GetResponse();
MemoryStream m = new MemoryStream();
response.GetResponseStream().CopyTo(m);
byte[] contents = m.ToArray();
As LB already said, you need to continue to call Read() until you have read the entire stream.
Although Stream.CopyTo will copy the entire stream it does not ensure that read the number of bytes expected. The following method will solve this and raise an IOException if it does not read the length specified...
public static void Copy(Stream input, Stream output, long length)
{
byte[] bytes = new byte[65536];
long bytesRead = 0;
int len = 0;
while (0 != (len = input.Read(bytes, 0, Math.Min(bytes.Length, (int)Math.Min(int.MaxValue, length - bytesRead)))))
{
output.Write(bytes, 0, len);
bytesRead = bytesRead + len;
}
output.Flush();
if (bytesRead != length)
throw new IOException();
}

Categories

Resources