在Java中使用Spring MVC进行分块文件上传?

huangapple 未分类评论48阅读模式
英文:

Chunked file upload in Java with Spring MVC?

问题

在我的项目中,我被指派开发一段能够处理大型文件上传的代码。这些文件可以是 PDF、图片等。我需要获取这个文件并将其保存在数据库中。客户端将使用 React,React 将以分块的形式发送数据。后端代码使用 Java 和 Spring MVC 编写。目前,它并没有将数据作为分块发送,这导致浏览器内存出现问题。

基本场景是用户将上传一个大文件,比如 200 MB,前端将把它作为小数据包发送到后端,即分块。

目前我们拥有的代码是:

@RequestMapping(value = "/intake/{channel}/attachment", method = RequestMethod.POST)
@ResponseBody
public JsonResponse uploadAttachment(final MultipartHttpServletRequest request,
        @PathVariable(name = "xxxx") String xxxxx, final HttpSession session,
        @RequestParam(name = "xxxxx", required = false, defaultValue = "") String xxxxx,
        @RequestParam(name = "xxxxxx", required = false, defaultValue = "") String xxxxxx,
        @RequestParam(name = "unzip", required = false, defaultValue = "true") boolean unzip,
        @RequestParam(name = "xxx",required = false) String xxx) {

    JsonResponse jsonResponse = new JsonResponse();
    List<String> docsetIds = new ArrayList<>();
    List<String> parentDocsetIds = new ArrayList<>();
    WorklistActionResponse response = null;
    boolean isLiterature = false;

    try {
        List<MultipartFile> files = request.getFiles("attachment");
        if (files != null) {
            String rootURL = CommonUtils.getRootURL(request);
            for (Iterator iterator = files.iterator(); iterator.hasNext();) {
                MultipartFile multipartFile = (MultipartFile) iterator.next();

                FileContent fileContent = new FileContent();
                    fileContent.setContentLength(multipartFile.getSize());
                    fileContent.setContentType(multipartFile.getContentType());
                    fileContent.setInputStream(multipartFile.getInputStream());
                    fileContent.setName(multipartFile.getOriginalFilename());
                    String filePath = multipartFile.getOriginalFilename();
                    String filePathParts[] = filePath.split("/");
                    String fileName = filePathParts[filePathParts.length - 1];
                    String fileParts[] = fileName.split("\\.");
                    String fileExtension = fileParts[fileParts.length - 1];
                    fileContent.setFileExtention(fileExtension);
                    DocumentDetail subDocumentDetail = documentService.saveAttachment(
                            new NewAttachmentRequest(channel, groupId, rootURL, docsetId, fileContent), userId);
                    if (subDocumentDetail == null) {
                        throw new NotSupportedException();
                    }
                    if (subDocumentDetail != null) {
                        subDocumentDetails.add(subDocumentDetail);
                    }
                }
            }
       }
  }

这里的文件将会被 Multipart 请求接收。但这段代码并没有达到预期的目的。

我的问题是:

  1. Multipart 请求足够处理分块数据吗?
  2. 当数据以分块方式传入时,我需要做哪些修改或变更?也就是说,小数据包会不断地传送,直到上传完成。

我在 Stack Overflow 上找到了一些类似的答案:

但在 Stack Overflow 上,我也看到了很多相互矛盾的说法。

我该如何解决这个问题呢?

英文:

In my project, I am assigned to develop a code that can handle large documents to upload. Documents can be pdf, image, etc I need to get this file and save it in the database The client will be React and react will be sending the data as chunks. Backend code is written in Java with Spring MVC. Currently, it is not sending it as a chunk and this is causing memory issues in the Browser.

The basic scenario is the user will upload a large file for ex:200 MB and the front end will be sending it as small packets to backend ie, as chunks.

Currently whatever we have is ,

@RequestMapping(value = &quot;/intake/{channel}/attachment&quot;, method = RequestMethod.POST)
	@ResponseBody
	public JsonResponse uploadAttachment(final MultipartHttpServletRequest request,
			@PathVariable(name = &quot;xxxx&quot;) String xxxxx, final HttpSession session,
			@RequestParam(name = &quot;xxxxx&quot;, required = false, defaultValue = &quot;&quot;) String xxxxx,
			@RequestParam(name = &quot;xxxxxx&quot;, required = false, defaultValue = &quot;&quot;) String xxxxxx,
			@RequestParam(name = &quot;unzip&quot;, required = false, defaultValue = &quot;true&quot;) boolean unzip,
			@RequestParam(name = &quot;xxx&quot;,required = false) String xxx) {

	JsonResponse jsonResponse = new JsonResponse();
	List&lt;String&gt; docsetIds = new ArrayList&lt;&gt;();
	List&lt;String&gt; parentDocsetIds = new ArrayList&lt;&gt;();
	WorklistActionResponse response = null;
	boolean isLiterature = false;

	try {
		List&lt;MultipartFile&gt; files = request.getFiles(&quot;attachment&quot;);
		if (files != null) {
			String rootURL = CommonUtils.getRootURL(request);
			for (Iterator iterator = files.iterator(); iterator.hasNext();) {
				MultipartFile multipartFile = (MultipartFile) iterator.next();

				FileContent fileContent = new FileContent();
					fileContent.setContentLength(multipartFile.getSize());
					fileContent.setContentType(multipartFile.getContentType());
					fileContent.setInputStream(multipartFile.getInputStream());
					fileContent.setName(multipartFile.getOriginalFilename());
					String filePath = multipartFile.getOriginalFilename();
					String filePathParts[] = filePath.split(&quot;/&quot;);
					String fileName = filePathParts[filePathParts.length - 1];
					String fileParts[] = fileName.split(&quot;\\.&quot;);
					String fileExtension = fileParts[fileParts.length - 1];
					fileContent.setFileExtention(fileExtension);
					DocumentDetail subDocumentDetail = documentService.saveAttachment(
							new NewAttachmentRequest(channel, groupId, rootURL, docsetId, fileContent), userId);
					if (subDocumentDetail == null) {
						throw new NotSupportedException();
					}
					if (subDocumentDetail != null) {
						subDocumentDetails.add(subDocumentDetail);
					}
				}
			}
       }
  }

Here the document will be received by the Multipart request. This code is not serving the purpose

The questions I have is :

1, Is multipart request enough to handle chunked data as well.

2, What will be the modification/change I have to make when data comes in Chunk ie, small packets of data will keep on coming until the upload is complete.

I found some similar answers in Stack Overflow
https://stackoverflow.com/questions/40287355/fileupload-using-chunks-and-multipartfileupload

https://stackoverflow.com/questions/20334859/difference-between-multipart-and-chunked-protocol

https://stackoverflow.com/questions/20162474/how-do-i-receive-a-file-upload-in-spring-mvc-using-both-multipart-form-and-chunk

But I can see a lot of contradictory statements to these in Stack Overflow itself.

How can I fix this issue ?

huangapple
  • 本文由 发表于 2020年4月6日 13:17:40
  • 转载请务必保留本文链接:https://java.coder-hub.com/61053353.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定