Home > Blockchain >  How to get part of request body as input stream (request body mapped to multiple fields, one of them
How to get part of request body as input stream (request body mapped to multiple fields, one of them

Time:06-25

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!

CodePudding user response:

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  style="border:none;">Add project</h2>
    <input  th:field="*{title}" type="text">
    <textarea  th:field="*{description}" rows="4"></textarea>



    <input  type="hidden" th:field="*{videoName}" id="setVidName">
    <input  type="file" id="vidName" accept="video/mp4" name="file" onchange="setNameVar(this);">
    <button  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
  • Related