Super newbie to ASP.NET Core with React,
and try to build "upload file" functions.
From my react component,
I have input as follows, and trigger UploadFile function
<input type="file" onChange={(event) => UploadFile(event)} />
and in UploadFile function, it looks like this
function UploadFile(e) {
var file = e.target.files[0];
var formData = new FormData();
formData.append("file", file);
axios.post("/FileUpload/SingleFile", formData);
}
and the controller for SingleFile looks like this
public IActionResult SingleFile(IFormFile file)
{
using (var fileStream = new FileStream(Path.Combine(_dir, "file.png"), FileMode.Create, FileAccess.Write))
{
file.CopyTo(fileStream);
}
return RedirectToAction("Index");
}
But having a bit tricky time to figure out what is the right url path to pass on to the
axios.post(???, formData).
Is the path should be
"/'controller name'/'IActionResult method name'"??
With the current path, I get an 404 error which means wrong path.
Help!
The path I had was correct,
but the problem was that I was using ASP.NET Core 3.0
so I need to generate the antiforgery token.
The answer is listed here
Enable Antiforgery Token with ASP.NET Core and JQuery
Related
I want to upload image / file in a react project, but dont want to use formdata to post, instead i want to use body for the post method through Axios.
If I can convert my file into base 64, I think i will be able to post the image through body.
Can anyone tell me solution how to achieve this?
Use this code :
function encodeImageFileAsURL(element) {
var file = element.files[0];
var reader = new FileReader();
reader.onloadend = function() {
console.log('RESULT', reader.result)
}
reader.readAsDataURL(file);
}
I have a react app that contacts a backend dotnet controller to download various types of files. When I download most files everything works fine and the files are correct. When I download a json file, the file contains only [object Object]. Below is the code in the call method.
public downloadFile = async (fileId: number) => {
const response = await HttpUtility.postFileDownload<any>(DOWNLOAD_URL + fileId, {})
let fileName = response.headers['content-disposition'].split('filename=')[1].split('\'')[2]
if (fileName === undefined) {
fileName = `file-id-${fileId}-${moment().format()}`
}
fileDownload(response.data, fileName, response.headers['content-type'])
}
When, I look at the dev tools in Chrome, the response looks correct. Any pointers on what I need to do to correct this?
This May works
fileDownload(JSON.stringify(response.data), fileName, response.headers['content-type'])
I am working with Spring-3.9.3, creating Excel files and trying to download them from React. The code works fine with small file sizes (50kb), more than this means no response from the React localhost web.
I don't know how to fix the problem as I have no idea if the error comes from Spring or React library.
The code comes from a tutorial that you can find here:
https://rieckpil.de/howto-up-and-download-files-with-react-and-spring-boot/
//react code from react
class App extends Component {
downloadExcel = () => {
fetch('http://localhost:8080/api/files')
.then(response => {
const filename = response.headers.get('Content-Disposition').split('filename=')[1];
response.blob().then(blob => {
let url = window.URL.createObjectURL(blob);
let a = document.createElement('a');
a.href = url;
a.download = filename;
a.click();
});
});
}
render() {
return (
<div className="App-intro">
<h3>Download an excel file</h3>
<button onClick={this.downloadExcel}>Download</button>
</div>
)
}
}
And here there is the Spring code that I am using:
//spring
#RestController
#RequestMapping(method = RequestMethod.GET, value = "/api/files")
#CrossOrigin(value = {"*"}, exposedHeaders = {"Content-Disposition"})
public class FileBoundary{
#GetMapping
public void getEntitiesXLS(HttpServletRequest request, HttpServletResponse response) throws Exception, IOException, InvalidFormatException{
Workbook workbook = new XSSFWorkbook();
Sheet sheet = workbook.createSheet("Contacts");
//create the excel file with Apache POI library
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=\"tickets.xlsx\"");
workbook.write(response.getOutputStream());
}
}
I can see the request in Spring console but there is no response in the React web. Anyone knows a solution for this? Thanks!
Well, the problem was the timeout response of the micro.
I am trying to do a file upload functionality, where my front end contains react and server is asp.net core 2. I tried with various combinations but my code is not working.(Getting error at server end and most likely getting content-type error). Following is the snippets for both front end and server:
React Code is:
const formData: any = new FormData();<br />
formData.append("File",data[0]); // data[0] contains the file object<br/>
return axios.post(SAVE_ATTACHMENT_DATA, formData,
{headers: { 'Content-Type':'multipart/form-data' }}
)
.then(resp => {
//
}, err => {
//
})
};
ASP.NET Core 2 Code is:
[HttpPost]
[Route("upload")]
public async Task<IActionResult> Upload()
{
var files = Request.Form.Files; // getting error here in "Form"
FileUploadViewModel model = new FileUploadViewModel(); // model been defined in another file
var file = model.File;
if (file.Length > 0)
{
string path = Path.Combine(#"temp\", "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();
}
Can some one please help me with the same.
It should work like this:
React Code
const formData = new FormData();
formData.append("file", data[0]);
return axios.post(SAVE_ATTACHMENT_DATA, formData)
ASP.NET Core 2:
[HttpPost]
[Route("upload")]
public async Task<IActionResult> Upload(IFormFile file)
{
if (file.Length > 0)
{
string path = Path.Combine(#"temp\", "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();
}
Important: The name of the file in React has to be the same as the parameter name in the .NET Core method or else the IFormFile will be null. For example formData.append('sameName', data[0]); in React and IFormFile sameName in .NET Core.
All you're doing in your action is newing up your model, which then, obviously isn't going to have any file uploads associated with it, because it was created manually by you and not from the post data. Instead, you should take your model as a param to your action, and then use that instance rather than creating your own:
[HttpPost]
[Route("upload")]
public async Task<IActionResult> Upload(FileUploadViewModel model)
I am using the File() constructor for creating file object for uploading a blob file to the server. The following code works fine for Chrome, but fails for Safari and Internet Explorer.
image_url = new File([blob],file_name,{type: mimeString});
The code is breaking at this line and getting this error in console "FileConstructor is not a constructor" (evaluating 'new File([blob],file_name,{type: mimeString})')
Using the FileReader API is an alternative to this but I am not able to fix this issue.
I Suggest to use the blob api, I've found the same problem and I solved like that:
var html = <svg>whatever on svg </svg>
var fileName = "myfile.svg";
var blob = new Blob([html], {type: 'image/svg'});
blob.lastModifiedDate = new Date();
// var blobAttrs = {type: "image/svg"};
// var file = new File([html], fileName, blobAttrs);
var formData = new FormData();
formData.append("file",blob,fileName);
It is not a "file", but you can use it like it was.
According to web "Can I use" Safari does not support the new File() constructor. See this link http://caniuse.com/#feat=fileapi
So I think you have to either use FileReader or maybe use some of the polyfills listed here https://github.com/Modernizr/Modernizr/wiki/HTML5-Cross-Browser-Polyfills
Especially this one could be useful for you https://github.com/mailru/FileAPI (I did not use it myself)
Also have a look at this SO answer What to use instead of FileReader for Safari?
If you can use ES6 classes:
class CustomFile extends Blob
{
constructor(blobParts, filename, options) {
super(blobParts, options);
this.name = filename || "";
if(options) {
this.lastModified = options.lastModified;
}
}
lastModified = 0;
name = "";
}
const blob = new Blob();
const fileObject = new CustomFile([blob],"myfile");
console.log(fileObject);
There is a File ponyfill on npm which works with modern module imports. This makes usage simple but you do need to import it in every module where you use new File().
import File from '#tanker/file-ponyfill';
const myFile = new File(['somefiledata'], 'example.txt', { type: 'text/plain'});