Send more than 1 file over HttpClient Post request c# - c#

I'm currently working with an API and I have to send files thanks to http post protocol.
With postman, everithing works fine and I can send an array of files that can contains more than 1 file:
For that, I'm using HttpClient in my c# application, but I only can send one file. Moreover, my body must contains form-data body so I created a MultipartFormDataContent object for send my file.
public async Task<SubmitIdentityResults> SubmitIdentity(Guid companyId, DocumentTypes docType, SubmitIdentityParameters submitIdentityParameters)
{
try
{
var accesstoken = await _authTokenFromClientID.GetAccessToken();
var client = _httpClientFactory.CreateClient("MyClient");
client.DefaultRequestHeaders.Authorization = new System.Net.Http.Headers.AuthenticationHeaderValue("bearer", accesstoken);
MultipartFormDataContent form = new MultipartFormDataContent();
form.Add(new StreamContent(submitIdentityParameters.File!), "Files", submitIdentityParameters.FileName!);
var response = await client.PostAsync($"api/Document/{docType.ToString()}", form);
if (response.StatusCode == System.Net.HttpStatusCode.NoContent)
{
return default(SubmitIdentityResults)!;
}
return await response.Content.ReadFromJsonAsync<SubmitIdentityResults>() ?? default(SubmitIdentityResults)!;
}
catch (Exception)
{
throw;
}
}
There is a way to develop the same bahaviour in c# with httpclient and mulitipartformdata ?

I think you should pass an array SubmitIdentityParameters[] submitIdentityParameters and do like this.
foreach (var file in submitIdentityParameters)
{
form.Add(new StreamContent(file.File!), "Files", file.FileName!);
}

Related

Send a string in body via SendRequestAsync

I need to send a Patch request to a backend API via SendRequestAsync func. This is regarding a UWP C# app.
Backend expected to like this:
On the app this is the code I wrote. But doesn't work
if (requestMehtod == ApplicationConstants.RequestType.PATCH)
{
Uri uri = new Uri(requestUrl);
HttpRequestMessage requestMessage = null;
if (postData != null)
{
var itemAsJson = JsonConvert.SerializeObject(postData);
requestMessage = new HttpRequestMessage(HttpMethod.Patch, uri)
{
Content = new HttpStringContent(itemAsJson, Windows.Storage.Streams.UnicodeEncoding.Utf8, "application/json-patch+json")
};
}
else
{
requestMessage = new HttpRequestMessage(HttpMethod.Patch, uri);
}
response = await httpClient.SendRequestAsync(requestMessage).AsTask(cancellationTokenSource.Token);
var rdModel = ProcessResponseData(response);
return await Handle401Error(rdModel, response, postData, url, requestMehtod, isDownloadSite, OnSendRequestProgress, requestData);
}
The above code fine to send JSON data to the same API and works fine. But I need to know how to send just a string in the body. Thank for the consideration
NOTE: App uses HttpClient from Windows.Web.Http and will not be able to use anything inside System.Net.Http namespace.
The answer is given by the #gusman and #Simon Wilson. Just to amend to their answer, in order to be able to send a string in the request body, the string needs to be within double-quotes.
var requestData = "\"hello world\"";
var request = new HttpRequestMessage(HttpMethod.Post, uri)
{
Content = new HttpStringContent(requestData, Windows.Storage.Streams.UnicodeEncoding.Utf8, "application/json")
};
response = await httpClient.SendRequestAsync(request);
This worked in my scenario.

Pass files to another asp.net core webapi from another webapi

Existed asp.net core Api is look like below
public async Task<IActionResult> UploadAsync()
{
IFormFile file = null;
var files = Request.Form.Files;
if (files.Count > 0)
{
file = Request.Form.Files[0];
var fileText = new StringBuilder();
using (var reader = new StreamReader(file.OpenReadStream()))
{
while (reader.Peek() >= 0)
fileText.AppendLine(reader.ReadLine());
}
int stagingDetailId = await _stagingMarketProvider.GetV1StagingStatusDetailId();
var result = await SaveStagingMarketsAsync(_fileProvider.ReadImportedMarkets(fileText.ToString()));
return Ok(result);
}
return Ok();
}
Now to consume that api from another asp.net core webapi, I have to pass those files through Request object only, I can't change any existed Api code because of business.
Solution 1: Applicable if you want your client to get redirected to other API
Assuming the API caller understands HTTP 302 and can act accordingly, the 302 redirect should help you.
public IActionResult Post()
{
return Redirect("http://file-handler-api/action");
}
From documentation, Redirect method returns 302 or 301 response to client.
Solution 2: C# Code To Post a File Using HttpClient
Below c# code is from this blog post. This is simple code which creates HttpClient object and tries to send the file to a web API.
As you are doing this from one API to another, you will have to save file first at temporary location. That temporary location will be parameter to this method.
Also, After upload you may want to delete the file if it is not required. This private method you can call after file upload to your first API is complete.
private async Task<string> UploadFile(string filePath)
{
_logger.LogInformation($"Uploading a text file [{filePath}].");
if (string.IsNullOrWhiteSpace(filePath))
{
throw new ArgumentNullException(nameof(filePath));
}
if (!File.Exists(filePath))
{
throw new FileNotFoundException($"File [{filePath}] not found.");
}
using var form = new MultipartFormDataContent();
using var fileContent = new ByteArrayContent(await File.ReadAllBytesAsync(filePath));
fileContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");
form.Add(fileContent, "file", Path.GetFileName(filePath));
form.Add(new StringContent("789"), "userId");
form.Add(new StringContent("some comments"), "comment");
form.Add(new StringContent("true"), "isPrimary");
var response = await _httpClient.PostAsync($"{_url}/api/files", form);
response.EnsureSuccessStatusCode();
var responseContent = await response.Content.ReadAsStringAsync();
var result = JsonSerializer.Deserialize<FileUploadResult>(responseContent);
_logger.LogInformation("Uploading is complete.");
return result.Guid;
}
Hope this helps you.

How to send File Object to Web api using POST call in Xamarin forms.?

I need to make a POST call from my Xamarin forms app where I need to upload a file object as it is to API using POST Call. Is there any way to make it possible?
if you send file object using Base64 or Byte[] then it will allowed only limited may be upto 2-4 Mb but if you have a larger image than that it will not support.
So, Solution is Post Stream Content Like,
var file = await CrossMedia.Current.PickPhotoAsync(new PickMediaOptions
{
PhotoSize = PhotoSize.Full,
CompressionQuality = 100
});
Create Object of MediaFile like, public MediaFile AttachedImage; and Store file into it so Memory stream will not lost. Like,AttachedImage = file
Post Code on API,
HttpClient httpClient = new HttpClient();
MultipartFormDataContent mt = new MultipartFormDataContent();
AttachedImage.GetStream().Position = 0;
StreamContent imagePart = new StreamContent(AttachedImage.GetStream());
imagePart.Headers.Add("Content-Type", ImageType);
mt.Add(imagePart, String.Format("file"), String.Format("bk.jpeg"));
requestMessage.Content = mt;
var response = await httpClient.PostAsync("Your URL", mt);
if (response.IsSuccessStatusCode)
{
var responseString = await response.Content.ReadAsStringAsync();
var objRootObjectuploadImage = JsonConvert.DeserializeObject<RootObjectuploadImage>(responseString);
if (objRootObjectuploadImage != null)
{
}
else
{
}
}
else
{
Loading(ActIndicator, false);
await DisplayAlert(res.LAlert, "webserver not responding.", res.LOk);
}
NO, it is not possible to send file object. You can send as a json by converting the file in the Base64 string. This is the advised proven solution. This link has code for converting back and forth from Base64.

.NET Core 1.0 read form-data posted file and put it in MultipartFormDataContent

I'm trying to fetch form-data sent to .NET Core API. The aim is to redirect the post request to another API.
I don't want the file to be stored locally but only "transmitted" again in a request.
Here is the code I'm trying.
MultipartFormDataContent multipartContent = new MultipartFormDataContent();
multipartContent.Add(new StringContent(Request.Form["id"]), "id");
var file = Request.Form.Files[0];
if (file.Length > 0)
{
var fileStreamContent = new StreamContent(Request.Form.Files[0].OpenReadStream());
multipartContent.Add(fileStreamContent, Request.Form.Files[0].FileName);
client.BaseAddress = new Uri("http://example.com:8000");
client.DefaultRequestHeaders.Accept.Clear();
HttpResponseMessage response = await client.PostAsync("/document/upload", multipartContent);
if (response.IsSuccessStatusCode)
{
retValue = await response.Content.ReadAsAsync<DocumentUploadResult>();
}
}
It seems Request.Form.Files[0].OpenReadStream() doesn't work, as the request received by remote api is empty. The openReadStream was suggested by VS2015 as the former .FileStream i used before .NET Core seems not to be present anymore.
Is my idea to try to create a StreamContent from the file actually a good idea? Is there any better type I could use to transmit my file accepted by MultripartFormDataContent?
In order to read a file from a form post, have your Action accept an IFormFile parameter:
public async Task<IActionResult> UploadFile(IFormFile file){
byte[] bytes = new byte[file.Length];
using (var reader = file.OpenReadStream())
{
await reader.ReadAsync(bytes, 0, (int)file.Length);
}
}

Sending HTTP Request with a file AND strings as post parameters using HttpClient

Hi I'm writing a Windows Phone 8.1 Application, In this app i need to send a request to the Sonic API server, the request should contain a access_id (string) a format (string) and input_file (mp3 file) , I'm stuck with putting both the file and the string in one request : this is what I've tried :
public async static Task<string> RequestSong(StorageFile mp3File, string responseFormat)
{
try
{
using (var webClient = new HttpClient())
{
using (var form = new MultipartFormDataContent())
{
var mp3FileByteArray = await readBytesFromStorageFile(mp3File);
form.Add(new StringContent(ApiAccessId), "access_id");
form.Add(new StringContent(responseFormat), "format");
form.Add(new ByteArrayContent(mp3FileByteArray, 0, mp3FileByteArray.Count()), "input_file", mp3File.Name);
HttpResponseMessage responseMessage = await webClient.PostAsync(ApiAccessUrl, form);
//responseMessage.EnsureSuccessStatusCode();
string responseString = responseMessage.Content.ReadAsStringAsync().Result;
return responseString;
}
}
}
catch (Exception e)
{
//handle this
}
return "";
}
the request executes successfully but it says that missing or wrong access_id , access_id is used to access the sonic API and every user have a unique one, this does not work i guess because the parameters access_id and format are put in the request in a wrong content type(just guessing). because if i put the strings in formUrlEncodedContent, it works fine but i'm not able to upload the file with FormUrlEncodedContent.
Is there any way i can send the file and the strings both in the same request??
BTW it's System.NET.Http namespace.
Your access_id should be sent as a querystring parameter in your url.
ApiAccessUrl += "?access_id=" + ApiAccessId;
And remove the following line:
form.Add(new StringContent(ApiAccessId), "access_id");

Categories