send byte array by HTTP POST in store app
I'm trying to send some images + some meta data to a server by HTTP post from a windows store app but get stuck when trying to actually include the data in the post. It cannot be done the way you would accomplish this in a windows forms app or similar due to the changes to the store app API.
I get the error.
cannot convert source type byte[] to target type System.Net.Http.httpContent
now this is obviously because it's 2 different types that can't be implicitly casted, but it's basically what I'm looking to be able to do. How do I make get my byte array data into the httpContent type so I can include it in the following call
httpClient.PostAsync(Uri uri,HttpContent content);
here's my full upload method:
async private Task UploadPhotos(List<Photo> photoCollection, string recipient, string format)
{
PhotoDataGroupDTO photoGroupDTO = PhotoSessionMapper.Map(photoCollection);
try
{
var client = new HttpClient();
client.MaxResponseContentBufferSize = 256000;
client.DefaultRequestHeaders.Add("Upload", "Mozilla/5.0 (compatible; MSIE 10.0; Windows NT 6.2; WOW64; Trident/6.0)");
// POST action_begin
const string actionBeginUri = "http://localhost:51139/PhotoService.axd?action=Begin";
HttpResponseMessage response = await client.GetAsync(actionBeginUri);
response.EnsureSuccessStatusCode();
string responseBodyAsText = await response.Content.ReadAsStringAsync();
string id = responseBodyAsText;
////
// POST action_upload
Uri actionUploadUri = new Uri("http://localhost:51139/PhotoService.axd?action=Upload&brand={0}&id={1}&name={2}.jpg");
var metaData = new Dictionary<string, string>()
{
{"Id", id},
{"Brand", "M3rror"}, //TODO: Denne tekst skal komme fra en konfigurationsfil.
{"Format", format},
{"Recipient", recipient}
};
string stringData = "";
foreach (string key in metaData.Keys)
{
string value;
metaData.TryGetValue(key, out value);
stringData += key + "=" + value + ",";
}
UTF8Encoding encoding = new UTF8Encoding();
byte[] byteData = encoding.GetBytes(stringData);
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, actionUploadUri);
// send meta data
// TODO get byte data in as content
HttpContent metaDataContent = byteData;
HttpResponseMessage actionUploadResponse = await client.PostAsync(actionUploadUri, metaDataContent);
actionUploadResponse.EnsureSuccessStatusCode();
responseBodyAsText = await actionUploadResponse.Content.ReadAsStringAsync();
// send photos
// TODO get byte data in as content
foreach (byte[] imageData in photoGroupDTO.PhotosData)
{
HttpContent imageContent = imageData;
actionUploadResponse = await client.PostAsync(actionUploadUri, imageContent);
actionUploadResponse.EnsureSuccessStatusCode();
responseBodyAsText = await actionUploadResponse.Content.ReadAsStringAsync();
}
////
// POST action_complete
const string actionCompleteUri = "http://localhost:51139/PhotoService.axd?action=Complete";
HttpResponseMessage actionCompleteResponse = await client.GetAsync(actionCompleteUri);
actionCompleteResponse.EnsureSuccessStatusCode();
responseBodyAsText = await actionCompleteResponse.Content.ReadAsStringAsync();
////
}
catch (HttpRequestException e)
{
}
catch (Exception e)
{
Debug.WriteLine(e.ToString());
}
}
Solution 1:
It will be more straightforward to use System.Net.Http.ByteArrayContent
. E.g:
// Converting byte[] into System.Net.Http.HttpContent.
byte[] data = new byte[] { 1, 2, 3, 4, 5};
ByteArrayContent byteContent = new ByteArrayContent(data);
HttpResponseMessage reponse = await client.PostAsync(uri, byteContent);
For text only with an specific text encoding use:
// Convert string into System.Net.Http.HttpContent using UTF-8 encoding.
StringContent stringContent = new StringContent(
"blah blah",
System.Text.Encoding.UTF8);
HttpResponseMessage reponse = await client.PostAsync(uri, stringContent);
Or as you mentioned above, for text and images using multipart/form-data:
// Send binary data and string data in a single request.
MultipartFormDataContent multipartContent = new MultipartFormDataContent();
multipartContent.Add(byteContent);
multipartContent.Add(stringContent);
HttpResponseMessage reponse = await client.PostAsync(uri, multipartContent);
Solution 2:
You need to wrap the byte array in an HttpContent type.
If you are using System,Net.Http.HttpClient:
HttpContent metaDataContent = new ByteArrayContent(byteData);
If you are using the preferred Windows.Web.Http.HttpClient:
Stream stream = new MemoryStream(byteData);
HttpContent metaDataContent = new HttpStreamContent(stream.AsInputStream());
Solution 3:
The concept you are looking for is called Serialization. Serialization means preparing your data (which could be heterogeneous and without a predefined strucutre) for storage or transmission. Then, when you need to use the data again, you do the opposite operation, deserialization, and get back the original data structure. The link above shows a few methods on how this could be done in C#.