Issue
Let's consider following scenario:
I need to upload very large file, other than that I need the name, version and author. I have created the following endpoint:
@PostMapping(path = "/upload", consumes = MediaType.APPLICATION_JSON_VALUE)
public ResponseEntity<String> upload(@RequestBody MyClass myClass) {
//do the upload using the content received as InputStream and return success
}
The MyClass.java:
public class MyClass {
private String name;
private String version;
private String author;
private InputStream fileContent;
// constructor, getters and setters
}
Example request body:
{
"name": "article",
"version": "1",
"author": "John Smith"
"fileContent": "ZmlsZUNvbnRlbnQg" //base64 encoded tgz/zip
}
So the whole case is to save the name,version and author e.g. in database, and then use the fileContent InputStream to stream it somewhere (as it is too big to have it as bytearray). Is something like that possible in spring? All help appreciated!
Solution
I have this function for uploading videos to a directory in my intellij workspace.
@RequestMapping(method = RequestMethod.POST, path = "/projects/save/video")
public String uploadVideo(@RequestParam("file") MultipartFile file, @ModelAttribute Project project) throws InterruptedException {
// check if file is empty
if (file.isEmpty()) {
System.out.println("No file");
return "redirect:/user/projects";
}
// normalize the file path
String fileName = StringUtils.cleanPath(file.getOriginalFilename());
// save the file on the local file system
try(InputStream inputStream = file.getInputStream()) {
Path path = Paths.get(VID_UPLOAD_DIR + fileName);
Files.copy(inputStream, path, StandardCopyOption.REPLACE_EXISTING);
File directory = new File(CLASS_DIR);
if (! directory.exists()) {
directory.mkdir();
}
Path classPath = Paths.get(CLASS_DIR + fileName);
Files.copy(path, classPath, StandardCopyOption.REPLACE_EXISTING);
}
catch (IOException e) {
e.printStackTrace();
}
String part="../videos/"+fileName;
System.out.println(file.getSize() + " <---[]---> " + part);
member.setVideo(part);
MemberDB.projects.get(0).setTitle(project.getTitle());
MemberDB.projects.get(0).setDescription(project.getDescription());
MemberDB.projects.get(0).setLanguage(project.getLanguage());
MemberDB.projects.get(0).setTechnology(project.getTechnology());
MemberDB.projects.get(0).setVideoName(project.getVideoName());
return "redirect:/user/projects";
}
Template (using thymeleaf) looks like this
<form action="#" th:action="@{/projects/save/video}" name="subform" method="post" id="addProject" th:object="${project}" enctype="multipart/form-data">
<h2 class="exempt" style="border:none;">Add project</h2>
<input class="exempt" th:field="*{title}" type="text">
<textarea class="exempt" th:field="*{description}" rows="4"></textarea>
<input class="exempt" type="hidden" th:field="*{videoName}" id="setVidName">
<input class="exempt" type="file" id="vidName" accept="video/mp4" name="file" onchange="setNameVar(this);">
<button class="exempt" type="button" onclick="submitForm();">Save project</button>
</form>
And in your application properties
- spring.servlet.multipart.max-file-size=200MB
- spring.servlet.multipart.max-request-size=200MB
- spring.servlet.multipart.enabled=true
Answered By - Lekan Swansons
Answer Checked By - Robin (JavaFixing Admin)