Reputation: 924
I'm new to both react.js and ASP.Net core 2.0. And now writing a project using ASP.Net core 2.0 as back end API and react.js as application interface (front end). I'd like to know how to upload file. I have tried as follow but in the Back end side the parameter value (IFromFile file) is always null. And it seems that file was not posted correctly. Here are my codes:
.Net core (API)
[HttpPost]
[Route("upload")]
public async Task Upload(IFormFile file)
{
if (file == null) throw new Exception("File is null");
if (file.Length == 0) throw new Exception("File is empty");
using (Stream stream = file.OpenReadStream())
{
using (var binaryReader = new BinaryReader(stream))
{
var fileContent = binaryReader.ReadBytes((int)file.Length);
// await _uploadService.AddFile(fileContent, file.FileName, file.ContentType);
}
}
}
React.js
handleClick(event){
event.preventDefault();
// console.log("handleClick",event);
var self = this;
var apiBaseUrl = axios.defaults.baseURL + "user/upload";
if(this.state.filesToBeSent.length>0){
var filesArray = this.state.filesToBeSent;
const reader = new FileReader();
for(var i in filesArray){
//console.log("files",filesArray[i][0]);
var file = filesArray[i][0];
axios.post(apiBaseUrl, {data: file});
}
alert("File upload completed");
}
else{
alert("Please select files first");
}
}
Please advise how can I solve the issue.
Upvotes: 9
Views: 23983
Reputation: 121
This answer is true but I have problem with saving an image in my API so I change the method as you see and then work nice. You should set the parameter as [FromForm] in your API method
public async Task<IActionResult> Upload([FromForm]FileUploadViewModel model){...}
Upvotes: 4
Reputation: 319
In my case i simply missed to add multipart/form-data in my form.
If your controller is accepting uploaded files using IFormFile but you find that the value is always null, confirm that your HTML form is specifying an enctype value of multipart/form-data. If this attribute isn't set on the element, the file upload won't occur and any bound IFormFile arguments will be null.
Example:-
<form method="post" enctype="multipart/form-data" asp-controller="UploadFiles" asp-action="Index">
<div class="form-group">
<div class="col-md-10">
<p>Upload one or more files using this form:</p>
<input type="file" name="files" multiple />
</div>
</div>
<div class="form-group">
<div class="col-md-10">
<input type="submit" value="Upload" />
</div>
</div>
</form>
Remove the multiple attribute on this input element to allow just a single file to be uploaded.
Upvotes: 1
Reputation: 639
[Route("api/[controller]")]
[ApiController]
public class UploaderController : ControllerBase
{
[HttpPost]
public dynamic UploadJustFile(IFormCollection form)
{
try
{
foreach (var file in form.Files)
{
string path = Path.Combine(@"C:\uploadFiles");
using (var fs = new FileStream(Path.Combine(path, file.FileName), FileMode.Create))
{
file.CopyToAsync(fs);
}
UploadFile(file);
}
return new { Success = true };
}
catch (Exception ex)
{
return new { Success = false, ex.Message };
}
}
and in UI use this
uploadJustFile(e) {
e.preventDefault();
let state = this.state;
this.setState({
...state,
justFileServiceResponse: 'Please wait'
});
if (!state.hasOwnProperty('files')) {
this.setState({
...state,
justFileServiceResponse: 'First select a file!'
});
return;
}
let form = new FormData();
for (var index = 0; index < state.files.length; index++) {
var element = state.files[index];
form.append('file', element);
}
debugger;
axios.post('/api/uploader', form)
.then((result) => {
let message = "Success!"
if (!result.data.success) {
message = result.data.message;
}
this.setState({
...state,
justFileServiceResponse: message
});
})
.catch((ex) => {
console.error(ex);
});
}
Upvotes: 2
Reputation: 924
I have done the job as follow:
at .Net core 2.0 web api
using Microsoft.AspNetCore.Http;
I created a model class
namespace Marter_MRM.Models
{
public class FileUploadViewModel
{
public IFormFile File { get; set; }
public string source { get; set; }
public long Size { get; set; }
public int Width { get; set; }
public int Height { get; set; }
public string Extension { get; set; }
}
}
And then I created a controller class and wrote the function as follow.
[HttpPost]
[Route("upload")]
public async Task<IActionResult> Upload(FileUploadViewModel model) {
var file = model.File;
if (file.Length > 0) {
string path = Path.Combine(_env.WebRootPath, "uploadFiles");
using (var fs = new FileStream(Path.Combine(path, file.FileName), FileMode.Create))
{
await file.CopyToAsync(fs);
}
model.source = $"/uploadFiles{file.FileName}";
model.Extension = Path.GetExtension(file.FileName).Substring(1);
}
return BadRequest();
}
And write api call function in react as follow:
handleUploadClick(event){
event.preventDefault();
var self = this;
var apiBaseUrl = axios.defaults.baseURL + "user/upload";
if(this.state.filesToBeSent.length>0){
var filesArray = this.state.filesToBeSent;
let f = new FormData();
for(var i in filesArray){
//console.log("files",filesArray[i][0]);
f = new FormData();
f.append("File",filesArray[i][0] )
axios.post(apiBaseUrl, f, {
headers: {'Content-Type': 'multipart/form-data'}
});
}
alert("File upload completed");
}
else{
alert("Please select files first");
}
}
It works perfect. Thanks!
Upvotes: 13