How to receive MultipartFormDataContent in API? - c#

Net core application. I have one rest API which will send files to another API.
Below is the logic inside first API to send files to second API.
using (var client = new HttpClient())
{
client.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue("Bearer", await _tokenService.GetToken());
MultipartFormDataContent multipartFormData = new MultipartFormDataContent();
string contentJson = JsonConvert.SerializeObject(request);
HttpContent data = new StringContent(contentJson, Encoding.UTF8, "application/json");
multipartFormData.Add(data, "data");
foreach (var file in fileList)
{
if (file.Length <= 0)
continue;
var fileName = ContentDispositionHeaderValue.Parse(file.ContentDisposition).FileName.Trim('"');
multipartFormData.Add(new StreamContent(file.OpenReadStream())
{
Headers =
{
ContentLength = file.Length,
ContentType = new MediaTypeHeaderValue(file.ContentType)
}
}, "File", fileName);
}
try
{
var response = await client.PostAsync("https://localhost:44370/apisendfile", multipartFormData);
}
catch (Exception ex)
{
}
}
I have second API as below
public async Task<ActionResult> SendMail([FromBody] MultipartFormDataContent formDataContent)
{
}
When I debug in my first API I receive error
Unsupported Media Type
I am trying all the way to figure it out but could not succeed. Can someone help me to identify this issue. Any help would be appreciated. Thanks

Well, you could try following way,
Web API Controller:
[HttpPost]
public string UploadMultipartFile()
{
var file = HttpContext.Current.Request.Files.Count > 0 ?
HttpContext.Current.Request.Files[0] : null;
if (file != null && file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var path = Path.Combine(
HttpContext.Current.Server.MapPath("~/MrPerfectMaltipartFolder"),
fileName
);
file.SaveAs(path);
}
return file != null ? "/MrPerfectMaltipartFolder/" + file.FileName : null;
}
Folder Location:
Tested on Post Man:
Open Folder Location:
File Uploaded:
For N Type of Multipart Data Upload:
[HttpPost]
public object UploadMultipartFileList()
{
var uploadedFilesName = new List<string>();
if (HttpContext.Current.Request.Files.Count > 0)
{
int count = 0;
foreach (var item in HttpContext.Current.Request.Files)
{
var getFile = HttpContext.Current.Request.Files[count];
if (getFile != null)
{
var fileName = Path.GetFileName(getFile.FileName);
var path = Path.Combine(
HttpContext.Current.Server.MapPath("~/MrPerfectMaltipartFolder"),
fileName
);
getFile.SaveAs(path);
}
count++;
string file = "/MrPerfectMaltipartFolder/" + getFile.FileName;
uploadedFilesName.Add(file);
}
}
return uploadedFilesName;
}
Output:
Example Both Data and File:
[HttpPost]
public object UploadMultipartFileList()
{
HttpRequest multipartRquest = HttpContext.Current.Request;
//General Data Part
string engineerName = multipartRquest.Form["EngineerName"];
string engineerEmail = multipartRquest.Form["EngineerEmail"];
//File Upload Part
var FilesName = new List<string>();
if (HttpContext.Current.Request.Files.Count > 0)
{
int count = 0;
foreach (var item in HttpContext.Current.Request.Files)
{
var getFile = HttpContext.Current.Request.Files[count];
if (getFile != null)
{
var fileName = Path.GetFileName(getFile.FileName);
var path = Path.Combine(
HttpContext.Current.Server.MapPath("~/MrPerfectMaltipartFolder"),
fileName
);
getFile.SaveAs(path);
}
count++;
string file = "/MrPerfectMaltipartFolder/" + getFile.FileName;
FilesName.Add(file);
}
}
return FilesName;
}
Request Format:
Output:
Hope it would resolve your problem. Feel free to share if you still encounter any issues.

Correct API style :
[HttpPost("logfiles")] // etc
public async Task<IActionResult> AddLogFile(IFormFile reportFile)
{
//UploadFile with any options with correct property Name = "ReportFile"
// all assigment will do framework itself in default impl
if (reportFile == null || reportFile.Length <= 0)
{
Submit client side style :
using (MultipartFormDataContent httpContent = new MultipartFormDataContent())
{
// read bytes from memstream etc
//...
httpContent.Add((HttpContent) bytes, "ReportFile", "test.log");

Related

How to give a file name to uploadFile EF C#

I am uploading a file and wish to name it with one of the input fields which I wille be typing in my view. For ex: I type "Test" in my "Designation Commerciale" field. However, it gives me the NullReferenceException as it does not find any. Would appreciate your help. Thanks.
Controller:
public async Task<string> UploadFile(IFormFile file)
{
//bool iscopied;
string resp = String.Empty;
try
{
if (file.Length > 0)
{
var model = new IdentificationProduitViewModel();
string x = model.DesignationCommerciale;
string filename = x + Path.GetExtension(file.FileName);
string path = Path.GetFullPath(Path.Combine(Directory.GetCurrentDirectory(), "UploadFds"));
using (var filestream = new FileStream(Path.Combine(path, filename), FileMode.Create))
{
await file.CopyToAsync(filestream);
}
//iscopied = true;
resp = filename;
}
else
{
// iscopied = false;
resp = String.Empty;
}
}
catch(Exception)
{
throw;
}
return resp;
}
HTTPPOST:
string tryupload = await UploadFile(file_fds);
if (!String.IsNullOrEmpty(tryupload))
{
TempData["uploadok"] = "Fichier chargé avec success !";
model.Fds_Filepath = tryupload;
}

Response 400 on the post of httpclient in dotnet core

I am wrote the code to POST from my web application but it is sending 400 bad request.
See the my controller class:
[HttpPost]
public async Task<IActionResult> CreateAgent(AgentCreateDto agentCreateDto)
{
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://localhost:44331/api/");
var responseTask = client.PostAsJsonAsync("Agent/CreateAgent", agentCreateDto);
responseTask.Wait();
var result = responseTask.Result;
if (result.IsSuccessStatusCode)
{
var newAgentAdd = JsonConvert.DeserializeObject<AgentCreateDto>(await result.Content.ReadAsStringAsync());
var newAgent = newAgentAdd;
TempData["SuccessMessage"] = $"Agent {newAgent.FirstName} was successfully created.";
return RedirectToAction("AgentLists");
//return RedirectToAction("GetAgentById", new { AgentId = newAgent.usersId});
}
}
return View();
}
Here is below the problem image please see for the reference.
Here is api code for that I am send the request:
[HttpPost("CreateAgent")]
public async Task<IActionResult> CreateAgent([FromForm]AgentCreateDto agentCreateDto)
{
if (!ModelState.IsValid)
{
return BadRequest("Invalid model object");
}
if (agentCreateDto.ProfileImage != null)
{
string uniqueFileName = UploadProfileImage(agentCreateDto.ProfileImage);
agentCreateDto.ProfileNewImage = uniqueFileName;
}
var createAgent = await _userService.CreateAgent(agentCreateDto);
//_logger.LogInformation($"User added to the for file test. ");
return Created("", new
{
Id = createAgent.UsersId,
Message = "Agent created Successfully",
Status = "Success",
UserType = createAgent.UserType
});
}
And for image uploading code at the API side:
private string UploadProfileImage(IFormFile ProfileImage)
{
string uniqueFileName = null;
if (ProfileImage != null)
{
string uploadsFolder = Path.Combine(_webHostEnvironment.ContentRootPath, "ProfileImage");
uniqueFileName = Guid.NewGuid().ToString() + "_" + ProfileImage.FileName;
string filePath = Path.Combine(uploadsFolder, uniqueFileName);
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
ProfileImage.CopyTo(fileStream);
}
}
return uniqueFileName;
}
The correct way to post file and additional data by HttpClient like below:
using (var client = new HttpClient())
{
client.BaseAddress = new Uri("https://localhost:44331/api/");
var formContent = new MultipartFormDataContent();
formContent.Add(new StringContent(agentCreateDto.Id.ToString()), nameof(agentCreateDto.Id));
formContent.Add(new StringContent(agentCreateDto.Message), nameof(agentCreateDto.Message));
formContent.Add(new StringContent(agentCreateDto.UserType), nameof(agentCreateDto.UserType));
//other proerties....
formContent.Add(new StreamContent(agentCreateDto.ProfileImage.OpenReadStream()), nameof(agentCreateDto.ProfileImage), Path.GetFileName(agentCreateDto.ProfileImage.FileName));
//change PostAsJsonAsync to PostAsync.....
var responseTask = client.PostAsync("/Agent/CreateAgent", formContent);
responseTask.Wait();
var result = responseTask.Result;
//more code...
}

Issue in multi fileupload object with extra json parameter in REST API in ASP.NET MVC using C#

I'm creating a REST API in which accepts a JSON string with 3 different fileUpload in form data.
Here is my API controller post method
public async Task<IHttpActionResult> Post()
{
if (!Request.Content.IsMimeMultipartContent())
{
return StatusCode(HttpStatusCode.UnsupportedMediaType);
}
var filesReadToProvider = await Request.Content.ReadAsMultipartAsync();
var obj = new SubmitReportModel();
var enggCommentImg = new List<FileModel>();
var concernAreaImg = new List<FileModel>();
var remarkImge = new List<FileModel>();
string UploadPath = ("~/Uploads/ReportsData");
Functions.CreateIfMissing(System.Web.Hosting.HostingEnvironment.MapPath(UploadPath));
foreach (var item in filesReadToProvider.Contents)
{
if (item.Headers.ContentDisposition.Name.Contains("jsonKey"))
{
var jsson = await item.ReadAsStringAsync();
obj = Newtonsoft.Json.JsonConvert.DeserializeObject<SubmitReportModel>(jsson);
}
else if (item.Headers.ContentDisposition.Name.Contains("enggCommentImg"))
{
_ = new FileModel();
var fileDataByteArray = await item.ReadAsByteArrayAsync();
FileModel objfile = await SaveFileAsync(fileDataByteArray);
enggCommentImg.Add(objfile);
}
else if (item.Headers.ContentDisposition.Name.Contains("concernAreaImg"))
{
_ = new FileModel();
var fileDataByteArray = await item.ReadAsByteArrayAsync();
FileModel objfile = await SaveFileAsync(fileDataByteArray);
concernAreaImg.Add(objfile);
}
else if (item.Headers.ContentDisposition.Name.Contains("remarkImge"))
{
_ = new FileModel();
var fileDataByteArray = await item.ReadAsByteArrayAsync();
FileModel objfile = await SaveFileAsync(fileDataByteArray);
remarkImge.Add(objfile);
}
}
return Ok();
}
private async Task<FileModel> SaveFileAsync(byte[] fileDataByteArray)
{
string uploadPath = ("~/Uploads/ReportsData");
var objfile = new FileModel();
var filename = uploadPath + "/" + ApiHelper.GetTimestamp() + ".jpg";
using (FileStream fs = new FileStream(System.Web.Hosting.HostingEnvironment.MapPath(filename), FileMode.OpenOrCreate, FileAccess.Write))
{
await fs.WriteAsync(fileDataByteArray, 0, fileDataByteArray.Length).ConfigureAwait(true);
}
objfile.Name = filename;
objfile.Type = "jpg";
return objfile;
}
This API works fine I got JSON plus multiple files in each file object as well.
It works very well when I debug using breakpoints and parse each step using f10. But when I try it without breakpoints, it only saves the first file.
Here is how I'm calling it using Postman:
I tried the same with making it synchronous but still, I get the same result - saving only one file.
Here is my synchronous POST API code
public object Post()
{
if (!Request.Content.IsMimeMultipartContent())
{
return StatusCode(HttpStatusCode.UnsupportedMediaType);
}
//var filesReadToProvider =Request.Content.ReadAsMultipartAsync().GetAwaiter().GetResult();
var filesReadToProvider = Task.Run(async () => await Request.Content.ReadAsMultipartAsync()).Result;
var obj = new SubmitReportModel();
var enggCommentImg = new List<FileModel>();
var concernAreaImg = new List<FileModel>();
var remarkImge = new List<FileModel>();
string UploadPath = ("~/Uploads/ReportsData");
Functions.CreateIfMissing(System.Web.Hosting.HostingEnvironment.MapPath(UploadPath));
foreach (var item in filesReadToProvider.Contents)
{
if (item.Headers.ContentDisposition.Name.Contains("jsonKey"))
{
var jsson = Task.Run(async () => await item.ReadAsStringAsync()).Result;
obj = Newtonsoft.Json.JsonConvert.DeserializeObject<SubmitReportModel>(jsson);
}
else if (item.Headers.ContentDisposition.Name.Contains("enggCommentImg"))
{
_ = new FileModel();
var fileDataByteArray = Task.Run(async () => await item.ReadAsByteArrayAsync()).Result;
if (fileDataByteArray.Length > 0)
{
FileModel objfile = SaveFiles(fileDataByteArray);
enggCommentImg.Add(objfile);
}
}
else if (item.Headers.ContentDisposition.Name.Contains("concernAreaImg"))
{
_ = new FileModel();
var corsrnArr = Task.Run(async () => await item.ReadAsByteArrayAsync()).Result;
if (corsrnArr.Length > 0)
{
FileModel objfile = SaveFiles(corsrnArr);
concernAreaImg.Add(objfile);
}
}
else if (item.Headers.ContentDisposition.Name.Contains("remarkImge"))
{
_ = new FileModel();
var remarkarr = Task.Run(async () => await item.ReadAsByteArrayAsync()).Result;
if (remarkarr.Length > 0)
{
FileModel objfile = SaveFiles(remarkarr);
remarkImge.Add(objfile);
}
}
}
return 1;
}
private FileModel SaveFiles(byte[] fileDataByteArray)
{
string uploadPath = ("~/Uploads/ReportsData");
var objfile = new FileModel();
var filename = uploadPath + "/" + ApiHelper.GetTimestamp() + ".jpg";
using (FileStream fs = new FileStream(System.Web.Hosting.HostingEnvironment.MapPath(filename), FileMode.OpenOrCreate, FileAccess.Write))
{
fs.Write(fileDataByteArray, 0, fileDataByteArray.Length);
}
objfile.Name = filename;
objfile.Type = "jpg";
return objfile;
}
I'm unable to figure what exactly wrong step I made in it as there is no error in it.
UPDATE:
As theGeneral advised, I do recheck all steps and created a log so
found that all images were getting upload within a second so all of
them receive the same timestamp as name, and as a result, only one
file was getting overwrite again and again.
Keeping this thread as it is as this API work for files + other data
(JSON string in my case) and may get helpful for others

How to resolve 400 error with bad request in update api when it is deployed

I am getting 400 error code with bad request while request to file upload API.
I built the back-end and front-end for file uploading in asp.net core and it works in localhost when I run it with IIS in my PC (using visual studio 2017).
Both of saving and updating API are working in my local but update API is not working if I deploy the code
front-end code like below:
public static async Task<HttpResponseMessage> UploadFile(string uploadUrl, string filePath, FFFileInfo fileInfo)
{
string fileName = fileInfo.Name + "." + fileInfo.Extension;
string contentType = MimeTypes.GetMimeType(filePath);
using (var hc = new HttpClient())
{
hc.DefaultRequestHeaders.Authorization = new AuthenticationHeaderValue(TokenType, AccessToken);
hc.DefaultRequestHeaders.Accept.Clear();
hc.DefaultRequestHeaders.Accept.Add(new MediaTypeWithQualityHeaderValue("application/json"));
Stream fileStream = new FileStream(filePath, FileMode.Open, FileAccess.Read);
StreamContent streamContent = CreateFileContent(fileStream, fileName, contentType);
// StreamContent streamContent = CreateFileContent(fileStream, "image.jpg", "image/jpeg"); // Multiple file upload
var requestContent = new MultipartFormDataContent("Upload Id" + DateTime.Now.ToString(CultureInfo.InvariantCulture));
requestContent.Add(streamContent, fileInfo.Name, fileName);
var progressContent = new ProgressableStreamContent(
requestContent,
4096,
(sent, total) =>
{
//Console.WriteLine("Uploading {0}/{1}", sent, total);
int percentage = (int) Math.Round((double)(100 * sent) / total);
Console.Write("\r{0}\t{1}%", fileInfo.Path, percentage);
if (sent == total)
{
Console.WriteLine();
}
});
var response = await hc.PostAsync(new Uri(uploadUrl), progressContent);
return response;
}
}
backend code like below:
[HttpPost]
[DisableFormValueModelBinding]
public async Task<IActionResult> UploadFiles([FromQuery] FFFileInfo fileinfo)
{
if (!MultipartRequestHelper.IsMultipartContentType(Request.ContentType))
{
return BadRequest($"Expected a multipart request, but got {Request.ContentType}");
}
authUser = User.ToAuthUser();
userId = authUser.UserId();
customerId = authUser.CustomerId();
Server.Model.File new_file = new Server.Model.File();
var boundary = MultipartRequestHelper.GetBoundary(MediaTypeHeaderValue.Parse(Request.ContentType), _defaultFormOptions.MultipartBoundaryLengthLimit);
var reader = new MultipartReader(boundary, HttpContext.Request.Body);
var section = await reader.ReadNextSectionAsync();
MemoryStream writeStream = new MemoryStream();
byte[] content = null;
while (section != null)
{
ContentDispositionHeaderValue contentDisposition;
var hasContentDispositionHeader = ContentDispositionHeaderValue.TryParse(section.ContentDisposition, out contentDisposition);
int chunkSize = 1024;
byte[] byte_file = new byte[chunkSize];
int bytesRead = 0;
new_file.File_Content = byte_file;
if (hasContentDispositionHeader)
{
if (MultipartRequestHelper.HasFileContentDisposition(contentDisposition))
{
//await section.Body.CopyToAsync(targetStream);
using (var byte_reader = new BinaryReader(section.Body))
{
do
{
bytesRead = byte_reader.Read(byte_file, 0, byte_file.Length);
if(bytesRead <= 0)
{
content = writeStream.ToArray();
}
writeStream.Write(byte_file, 0, bytesRead);
} while (bytesRead > 0);
content = writeStream.ToArray();
}
}
}
// Drains any remaining section body that has not been consumed and
// reads the headers for the next section.
section = await reader.ReadNextSectionAsync();
}
try
{
new_file = new Server.Model.File
{
File_Name = fileinfo.Name,
File_Path = fileinfo.Path,
File_Ext = fileinfo.Extension,
Check_Sum = fileinfo.Checksum,
ToolSerialNumber = fileinfo.ToolSerialNumber,
FileSize = fileinfo.Length,
File_Content = content,
UserId = userId,
CustomerId = customerId
};
}
catch (Exception ex)
{
return BadRequest(ex);
}
try
{
if (!fileService.isExist(new_file.File_Path, userId))
{
fileService.SaveFile(new_file);
}
else
{
Server.Model.File existing = fileService.GetFileByPath(new_file.File_Path, userId);
fileService.UpdateFile(existing, new_file);
}
//set file content to null to response with small data
new_file.File_Content = null;
return Ok(new_file);
}
catch (Exception ex)
{
logger.LogError("DB action error {0}", ex.ToString());
return BadRequest(ex);
}
}
As you can see the above code, saving and updating are using same code but only updating is not working when it is deployed.
It is very strange for me.
I found the solution.
This code was deployed by my client I couldn't check the database that he deployed.
Based on researching and testing, I got an idea that might be related with permission issue.
So, we check it for db.
At the end, we found that current user has insert, delete, select permission but have not update permission.
After granting the update permission, it is working perfectly

Uploaded image not able to view in Amazon s3

I uploaded the image to Amazon S3 Successfully but when I view the image it shows nothing.
My View :
public JsonResult Upload(SocialJobMediaModel socialJobMediaModel)
{
var imagePathErrorMessage = new ImagePathErrorMessage();
if (Request.Files.Count > 0)
{
_log = GetProcessorLogger("CompanyXcodes", "CompanyXcodes", 1);
StageMediaFileProcessor stageMediaFileProcessor = new StageMediaFileProcessor(_log);
imagePathErrorMessage = stageMediaFileProcessor.UploadMediaFilesToS3(Request.Files[0].InputStream, Request.Files[0].FileName,"1234");
}
}
public void BulkUpload(Stream stream, string fileName, NameValueCollection metadata, ILogger log = null)
{
// Prepare request
if (string.IsNullOrEmpty(AwsRegion))
{
Client = new AmazonS3Client(_awsAccessKey, _awsSecretKey);
}
else
{
var regionEndPoint = RegionEndpoint.GetBySystemName(AwsRegion);
Client = new AmazonS3Client(regionEndPoint);
}
var tu = new TransferUtility(Client);
var request = new TransferUtilityUploadRequest
{
InputStream = stream,
Key = KeyPath + fileName,
BucketName = BucketName,
CannedACL = S3CannedACL.PublicRead,
};
if (metadata != null)
{
foreach (var metaDataKey in metadata.AllKeys)
{
request.Metadata.Add(metaDataKey, metadata[metaDataKey]);
}
}
// Set up progress logging (if logger provided)
if (log != null)
request.UploadProgressEvent += (sender, e) =>
{
if (e.PercentDone % 10 == 0)
log.LogInfo("Uploaded {0} of {1} bytes ({2} %)", e.TransferredBytes, e.TotalBytes, e.PercentDone);
};
// Upload (synchronous)
tu.Upload(request);
}
I am able to upload the image Successfully but when I view the image it shows nothing.can any one help me on this
I tried to upload filepath instead of inputstream but it throws the error

Categories

Resources