I am using Spring Boot as backend server and I have a JavaScript frontend.
For sending data between front- and backend I’m using the Axios library, which usually works pretty fine.
The Problem:
The image looks like this in the (Chrome) browser console:
It’s a very very long alphanumeric string and that’s what I send to the server with the following code:
static uploadFiles(files) { const data = new FormData(); Object.keys(files).forEach(key => { data.append("files", new Blob([files[key]], { type: 'image/jpeg' })); }); const url = API_URL + "uploadFiles"; return axios.post(url, data, RestServices.getAuth({ "Content-Type": "multipart/form-data;boundary=gc0p4Jq0M2Yt08jU534c0p" })); }
I have no idea what the boundary
thing does but it worked to receive a file in the backend tho…
On backend (spring) side I successfully receive an array of MultipartFiles:
@RequestMapping(value = "/uploadFiles", method = RequestMethod.POST) @ResponseBody public boolean uploadFiles(HttpServletRequest request, @RequestParam("files") MultipartFile[] files) throws IOException { String filePath = Thread.currentThread().getContextClassLoader().getResource("assets/images/").getFile(); InputStream inputStream; OutputStream outputStream; for(MultipartFile file : files) { File newFile = new File(filePath + file.getOriginalFilename() + ".jpg"); inputStream = file.getInputStream(); if (!newFile.exists() && newFile.createNewFile()) { outputStream = new FileOutputStream(newFile); int read; byte[] bytes = new byte[1024]; while ((read = inputStream.read(bytes)) != -1) { outputStream.write(bytes, 0, read); } } System.out.println(newFile.getAbsolutePath()); } return true; }
I’ve also tried it file.transferTo(newFile);
instead of in- and outputstreams – which didn’t work either.
After that I get the following output, which means that the image was saved successfully:
/path/to/blob.jpg
If I check the path where the file was uploaded, there is a file named blob.jpg, but if I open it, the windows photo viewer has the following problem:
I’ve opened the image before and after upload with notepad++:
Before upload:
I think this is a byte array, but If I open the image after upload I get exactly the output of the browser. This means it didn’t get converted to a byte array (correct me if I’m wrong) and I believe that’s why it’s a corrupt image…
My questions are:
- What’s the problem?
- How can I fix it?
I really tried everything which crossed my mind but I ran out of ideas.
Thanks for your help! 🙂
I’ve read following *related* questions (but they **don’t** have an answer):
[Question1][5], [Question2][6], and **many** more…
Advertisement
Answer
I’ve finally found an answer on my own!
I think the problem was that I used the e.target.result
(which is used to show the image on the frontend) but insted I had to use the JS File object. The standard HTML 5 file input fields return those File objects (as I’ve read here).
The only thing I had to do now is to make a FormData object, append the File Object, set the FormData as Body and set the Content-Type header and that’s it!
const data = new FormData(); data.append("files", fileObject); return axios.post(url, data, { "Content-Type": "multipart/form-data" });
Those JS File Objects are recognized from Java as Multipart files:
@RequestMapping(value = "/uploadFiles", method = RequestMethod.POST) @ResponseBody public boolean uploadFiles(HttpServletRequest request, @RequestParam("files") MultipartFile[] files) { boolean transferSuccessful = true; for (MultipartFile file : files) { String extension = file.getOriginalFilename().substring(file.getOriginalFilename().lastIndexOf('.')); String newFileName = genRandomName() + extension; //set unique name when saving on server File newFile; File imageFolder = new File(imageBasePath); //check if parent folders exist else create it if(imageFolder .exists() || imageFolder .mkdirs()) { while ((newFile = new File(imageFolder .getAbsolutePath() + "\" + newFileName)).exists()) { newFileName = genRandomName(); //generate new name if file already exists } try { file.transferTo(newFile); } catch (IOException e) { e.printStackTrace(); transferSuccessful = false; } } else { LOG.error("Could not create folder at " + imageFolder.getAbsolutePath()); transferSuccessful = false; } } return transferSuccessful; }
I hope this is helpful 🙂