I'm working on a Windows 10 project, one of my tasks is to send files to server in multipart request, so I achieve that by the following code, it is working well and files received from server and task completed.
Code:
System.Net.Http.HttpContent stringContent = new System.Net.Http.StringContent(imageFileName);
System.Net.Http.HttpContent bytesContent;
var client = new System.Net.Http.HttpClient();
var formData = new System.Net.Http.MultipartFormDataContent();
formData.Add(stringContent, "type");
foreach (byte[] image in imageFileName.GetImagesList())
{
bytesContent = new System.Net.Http.ByteArrayContent(image);
bytesContent.Headers.ContentType = MediaTypeHeaderValue.Parse("image/jpeg");
formData.Add(bytesContent, "images", "file_" + imageFileName.GetImagesList().IndexOf(image) + ".jpg");
}
var response = client.PostAsync(resourceAddress, formData).Result;
Then when we've moved to production environment, the firewall rejected this request and caught multiple hack attempts such as:
Http Headers Injection
SQL Injection by '#'
rm execution attempt
Backtick command execution attempts
vi execution attempts ...... and many more ....
And all this attempts, are caught for the contents of the JPEG file!
So I though that I should use HttpStreamContent instead, and tried the following code:
HttpMultipartFormDataContent multipartContent = new HttpMultipartFormDataContent();
HttpStreamContent streamContent;
Stream stream;
foreach (byte[] image in imageFileName.GetImagesList())
{
stream = new MemoryStream(image);
streamContent = new HttpStreamContent(stream.AsInputStream());
streamContent.Headers.ContentType = new HttpMediaTypeHeaderValue("image/jpeg");
multipartContent.Add(streamContent, "images", "file_" + imageFileName.GetImagesList().IndexOf(image) + ".jpg");
}
multipartContent.Add(new HttpStringContent(imageFileName), "type");
HttpRequestMessage request = new HttpRequestMessage(HttpMethod.Post, resourceAddress);
request.Content = multipartContent;
HttpResponseMessage response = await httpClient.SendRequestAsync(request).AsTask(cts.Token);
But Unfortunately I've got same result.
And the most important point is that the same web service (which I'm trying to call) is required to be implemented on Android & IOS with same functionality (multipart request) so the request from Android & IOS will be passed through the same Firewall, and it is working well from Android & IOS even on production!!!!
Related
Am trying to upload an image with the help of Xam.plugin.media NuGet package. But am getting a 400 Bad Request.
Below is my method which uploads the image to the backend.
private async void UploadImage()
{
var token = Application.Current.Properties["token"].ToString();
var multiForm = new MultipartFormDataContent();
var imagFile = _mediaFile.AlbumPath;
var upfilebytes = File.ReadAllBytes(imagFile);
ByteArrayContent baContent = new ByteArrayContent(upfilebytes);
multiForm.Add(new StringContent("1"), "x");
multiForm.Add(new StringContent("100"), "y");
multiForm.Add(new StringContent("100"), "width");
multiForm.Add(new StringContent("100"), "height");
multiForm.Add(baContent, "file", Path.GetFileName(_mediaFile.AlbumPath));
var client = new HttpClient();
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", "eyJhbGciOiJIUzI1NiIsInR5cCI6" +
"IkpXVCJ9.eyJYwZi05MjhhLTRiZjctYjZkNi0wY2U1ODRkOGRjZmQiLCJ1bmlxdWVfbmFtZ" +
"SI6IjIwZDA0MDY3LTU3YzYtNGY2MC04ZDI5LTg1NzkxMmFmOWI2MSIsImNsdCI6ImVuLUdCIiwidHoiOiJ" +
"XLiBFdXJvcGUgU3RhbmRhtZSIsIm5iZiI6MTU1NjQ3NTMyNCwiZXhwIjoxNTU2NDgyNTI0LCJpY" +
"XQiOjE1NTY0NzUzMjQsImlzcyI6Imh0dHBzOi8vYXBpLnZpYS5zb2Z0d2FyZSIsImF1ZCI6Imh0dHBz" +
"Oi8vd3d3LnZpYS5zb2Z0d2FyZSJ9.z5rghA338FDAtoInFYugMgwIirrdl9CrsGKhS8ceoFI");
var response = await client.PostAsync(utils.Settings.BaseUrl + "/auth/Users/ChangeAvatar", multiForm);
Debug.WriteLine("--> * "+response.Content.ReadAsStreamAsync().Result);
Debug.WriteLine("response --> * "+_mediaFile.AlbumPath);
Debug.WriteLine("--> * " + response);
}
So according to what I have implemented, I thought everything could work out.
Below are the parameters needed by the backend, actually when I try testing the endpoint in postman it works fine, but the method above doesn't work.
This is what happens on postman everything works fine when I upload an image.
What could be missing in my code for uploading?
the service expects a parameter called "image" but you are passing a parameter named "file"
I have OneDrive & Google Drive successfully processing chunked download however Dropbox is giving me grief because I cannot get the correct http request path to the file.
I am not an expert in rest url's & endpoints, maybe someone can point me in the right direction for the acceptable dropbox request format for the latest UWP SDK.
using (var httpRequest = new HttpRequestMessage())
{
string url = "https://content.dropboxapi.com/1/files/auto" + uri;
string accessKey = ApplicationData.Current.LocalSettings.Values[CommonData.dropboxAccessToken_Key].ToString();
httpRequest.Method = HttpMethod.Get;
httpRequest.RequestUri = new Uri(url);
httpRequest.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", accessKey);
}
I have read docs on Dropbox and it is not clear on the formatting for me, also I could not find a clear example anywhere.
Thanks again!
According to your code, the problem here is in your authorization header. For Dropbox API, the correct authorization header should like following:
Authorization: Bearer <access token>
So we should change httpRequest.Headers.Authorization to
httpRequest.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", token);
Then your code should be albe to work. Using "file.mp3" under "temp" folder for example.
The code may like:
var uri = "/temp/file.mp3";
using (var httpClient = new HttpClient())
{
using (var httpRequest = new HttpRequestMessage())
{
string url = "https://content.dropboxapi.com/1/files/auto" + Uri.EscapeDataString(uri);
httpRequest.Method = HttpMethod.Get;
httpRequest.RequestUri = new Uri(url);
httpRequest.Headers.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("Bearer", accessToken);
var response = await httpClient.SendAsync(httpRequest);
if (response.IsSuccessStatusCode)
{
//TODO
}
}
}
I have a app in which user can record video and an api to upload recorded video to azure. I am using below code
HttpClientHandler handler = new HttpClientHandler();
handler.MaxRequestContentBufferSize = int.MaxValue;
using (HttpClient httpClient = new HttpClient(handler)
{
MaxResponseContentBufferSize = int.MaxValue
})
{
MultipartFormDataContent content = new MultipartFormDataContent();
content.Add(new ByteArrayContent(chunks), "file", fileName);
HttpResponseMessage response = null;
response = await httpClient.PostAsync(new Uri(url), content);
return await response.Content.ReadAsStringAsync();
}
This is working only when either connection is wifi or on 3G video is less than of 10 sec. When I tried to upload video of size around 20-30 MB than it fails. In response I got status code 404 Not Found.
I also tried another way to upload but caught same error.
At last, I have changed my api code and send request with 1 mb chunks.
I'm trying to migrate a Windows C# library to Windows Phone 8 and I'm forced to make some changes in how the library gets data from an online URI.
I'm using the BCL's HttpClient to perform my data retrieval and everything's fine for now.
The library also requires an upload feature, and I can't find a way to do this using th HttpClient.
Here's the code:
// Client setup
var httpclient = new HttpClient();
var request = new HttpRequestMessage(HttpMethod.Post, string.Format(SubmitURI, value));
// Add the headers
request.Headers.Add("header", header);
var postData = GetPostData();
var data = Encoding.UTF8.GetBytes(postData);
// Side question -> Content is null here!
request.Content.Headers.Add("ContentType", "multipart/form-data; boundary=" + Boundary);
// BEGIN ORIGINAL CODE
var stream = request.GetRequestStream();
stream.Write(data, 0, data.Length);
stream.Close();
// END ORIGINAL CODE
// Get response
var response = await httpclient.SendAsync(request);
var responseContent = new StreamReader(await response.Content.ReadAsStreamAsync()).ReadToEnd();
Between the BEGIN ORIGINAL CODE and END ORIGINAL CODE comments, there's the code that I'm not able to migrate, so that you can understand what it does and I may need to make it work on WP.
The other of the code is already working on WP, except for the
request.Content.Headers.Add("ContentType", "multipart/form-data; boundary=" + Boundary);
because, for some reasons, request.Content is null.
So my question is: how can I migrate those 3 lines to WP using HttpClient (or any better way)?
And, as a little side question, why is request.Content null?
EDIT: based on #Johan van der Slikke's answer I've edited my code. It compiles, but the server reports that no file was uploaded, so I guess that there are still some issues.
var stream = new MemoryStream(data);
var streamContent = new StreamContent(stream);
request.Content = streamContent;
request.Content.Headers.Add("ContentType", "multipart/form-data; boundary=" + Boundary);
// Get response
var response = await httpclient.SendAsync(request);
You should wrap your stream in the StreamContent class (a subclass of HttpContent) and send it with the HttpClient using the PostAsync or PutAsync methods.
Edit
You don't need to use HttpRequestMessage.
var stream = new MemoryStream(data);
var streamContent = new StreamContent(stream);
// Get response
var response = await httpclient.PostAsync(streamContent)
Also you don't need to create a MemoryStream with your byte array. You can wrap it in a ByteArrayContent directly.
var response = await httpclient.PostAsync(new ByteArrayContent(data))
Maybe (because I see you using multipart/form-data header) you should use MultipartFormDataContent classes or FormUrlEncodedContentClasses.
You can send multi-part content like this,
var client = new HttpClient();
var content = new MultipartContent();
content.Add(new ByteArrayContent(data));
var response = await client.PostAsync(SubmitUrl, content);
However, I am curious what media type your "PostData" is. You may want to set the content-type header on the ByteArrayContent.
I am creating a Metro App that makes a HTTP Post request to a webserver to obtain JSON data. Initially I use the same code to logon to the web server and the HTTP Post request returns fine. It is only later that I run into an issue where the code hangs when I call the SendAsync() method.
I used wireshark to view the network traffic and I did see the server returning a response. So I am not sure why the call is not completing. Anyone have any ideas?
Here is the code I am using:
var httpHandler = new HttpClientHandler();
httpHandler.CookieContainer = __CookieJar;
var httpClient = new HttpClient(httpHandler);
UserAgentDetails userAgent = UserAgentDetails.GetInstance();
httpClient.DefaultRequestHeaders.UserAgent.ParseAdd(userAgent.UserAgentString);
foreach (string key in __colHeaders)
httpClient.DefaultRequestHeaders.Add(key, __colHeaders[key]);
var content = new StringContent(postData);
if (contentType != null && contentType.Length > 0)
content.Headers.ContentType = new System.Net.Http.Headers.MediaTypeHeaderValue(contentType);
var requestMsg = new HttpRequestMessage(HttpMethod.Post, new Uri(url));
requestMsg.Content = content;
requestMsg.Headers.TransferEncodingChunked = true;
var responseMsg = await httpClient.SendAsync(requestMsg);
// no return from method after logon