当前位置: 首页 > 面试题库 >

SpringBoot:使用Apache Commons FileUpload的大型流文件上传

龙涵蓄
2023-03-14
问题内容

我正在尝试使用“流式” Apache Commons File Upload API上传大文件。

我使用Apache Commons File Uploader而不是默认的Spring Multipart Uploader的原因是,当我们上传非常大的文件大小(〜2GB)时,它失败了。我在GIS应用程序上工作,这种文件上传非常常见。

我的文件上传控制器的完整代码如下:

@Controller
public class FileUploadController {

    @RequestMapping(value="/upload", method=RequestMethod.POST)
    public void upload(HttpServletRequest request) {
        boolean isMultipart = ServletFileUpload.isMultipartContent(request);
        if (!isMultipart) {
            // Inform user about invalid request
            return;
        }

        //String filename = request.getParameter("name");

        // Create a new file upload handler
        ServletFileUpload upload = new ServletFileUpload();

        // Parse the request
        try {
            FileItemIterator iter = upload.getItemIterator(request);
            while (iter.hasNext()) {
                FileItemStream item = iter.next();
                String name = item.getFieldName();
                InputStream stream = item.openStream();
                if (item.isFormField()) {
                    System.out.println("Form field " + name + " with value " + Streams.asString(stream) + " detected.");
                } else {
                    System.out.println("File field " + name + " with file name " + item.getName() + " detected.");
                    // Process the input stream
                    OutputStream out = new FileOutputStream("incoming.gz");
                    IOUtils.copy(stream, out);
                    stream.close();
                    out.close();

                }
            }
        }catch (FileUploadException e){
            e.printStackTrace();
        }catch (IOException e){
            e.printStackTrace();
        }
    }

    @RequestMapping(value = "/uploader", method = RequestMethod.GET)
    public ModelAndView uploaderPage() {
        ModelAndView model = new ModelAndView();
        model.setViewName("uploader");
        return model;
    }

}

麻烦的是,getItemIterator(request)始终返回没有任何项目(即一个迭代器iter.hasNext())始终返回false

我的application.properties文件如下:

spring.datasource.driverClassName=org.postgresql.Driver
spring.datasource.url=jdbc:postgresql://localhost:19095/authdb
spring.datasource.username=georbis
spring.datasource.password=asdf123

logging.level.org.springframework.web=DEBUG

spring.jpa.hibernate.ddl-auto=update

multipart.maxFileSize: 128000MB
multipart.maxRequestSize: 128000MB

server.port=19091

的JSP视图/uploader如下:

<html>
<body>
<form method="POST" enctype="multipart/form-data" action="/upload">
    File to upload: <input type="file" name="file"><br />
    Name: <input type="text" name="name"><br /> <br />
    Press here to upload the file!<input type="submit" value="Upload">
    <input type="hidden" name="${_csrf.parameterName}" value="${_csrf.token}" />
</form>
</body>
</html>

我可能做错了什么?


问题答案:

感谢M.Deinum的一些非常有帮助的评论,我设法解决了这个问题。我已经整理了一些原始帖子,并将其作为完整答案发布,以备将来参考。

我犯的第一个错误是没有禁用MultipartResolverSpring提供的默认值。这最终导致解析器处理HttpServeletRequest并因此在我的控制器对其执行操作之前将其消耗掉。

感谢M. Deinum,禁用它的方法如下:

multipart.enabled=false

但是,此后还有另一个隐患等待着我。禁用默认的多部分解析器后,尝试进行上传时,我开始出现以下错误:

Fri Sep 25 20:23:47 IST 2015
There was an unexpected error (type=Method Not Allowed, status=405).
Request method 'POST' not supported

在我的安全配置中,我启用了CSRF保护。这就需要我以以下方式发送POST请求:

<html>
<body>
<form method="POST" enctype="multipart/form-data" action="/upload?${_csrf.parameterName}=${_csrf.token}">
    <input type="file" name="file"><br>
    <input type="submit" value="Upload">
</form>
</body>
</html>

我还对控制器做了一些修改:

@Controller
public class FileUploadController {
    @RequestMapping(value="/upload", method=RequestMethod.POST)
    public @ResponseBody Response<String> upload(HttpServletRequest request) {
        try {
            boolean isMultipart = ServletFileUpload.isMultipartContent(request);
            if (!isMultipart) {
                // Inform user about invalid request
                Response<String> responseObject = new Response<String>(false, "Not a multipart request.", "");
                return responseObject;
            }

            // Create a new file upload handler
            ServletFileUpload upload = new ServletFileUpload();

            // Parse the request
            FileItemIterator iter = upload.getItemIterator(request);
            while (iter.hasNext()) {
                FileItemStream item = iter.next();
                String name = item.getFieldName();
                InputStream stream = item.openStream();
                if (!item.isFormField()) {
                    String filename = item.getName();
                    // Process the input stream
                    OutputStream out = new FileOutputStream(filename);
                    IOUtils.copy(stream, out);
                    stream.close();
                    out.close();
                }
            }
        } catch (FileUploadException e) {
            return new Response<String>(false, "File upload error", e.toString());
        } catch (IOException e) {
            return new Response<String>(false, "Internal server IO error", e.toString());
        }

        return new Response<String>(true, "Success", "");
    }

    @RequestMapping(value = "/uploader", method = RequestMethod.GET)
    public ModelAndView uploaderPage() {
        ModelAndView model = new ModelAndView();
        model.setViewName("uploader");
        return model;
    }
}

其中Response只是我使用的一种简单的通用响应类型:

public class Response<T> {
    /** Boolean indicating if request succeeded **/
    private boolean status;

    /** Message indicating error if any **/
    private String message;

    /** Additional data that is part of this response **/
    private T data;

    public Response(boolean status, String message, T data) {
        this.status = status;
        this.message = message;
        this.data = data;
    }

    // Setters and getters
    ...
}


 类似资料:
  • 我试图使用“流式”Apache Commons文件上传API上传一个大文件。 我使用Apache Commons文件上传器而不是默认的Spring多部分上传器的原因是,当我们上传非常大的文件大小(~2GB)时,它会失败。我在一个GIS应用程序中工作,这样的文件上传非常常见。 我可能做错了什么?

  • 我们需要一个能够存储大量大型csv文件(1000个文件,每天每个1GB)的系统。 还有一些客户端应该连接到此系统并下载csv文件 系统应该容错和可扩展... 我考虑使用Hadoop集群并在其上运行FTP服务器。。。 Hadoop适合这个项目吗? 如果没有,什么技术是合适的?

  • 我也有这里提到的同样的问题。 然后我想把它作为一个上传体流到另一个服务endpoint。 该解决方案的生成方式如下:bodytype=org.springframework.web.reactive.function.bodyinserters不支持

  • 本文向大家介绍springboot 文件上传大小配置的方法,包括了springboot 文件上传大小配置的方法的使用技巧和注意事项,需要的朋友参考一下 springboot上传文件大小的配置我这里记录两种,一种是设置在配置文件里只有两行代码,一种是加个Bean 首先第一种: application.properties中添加 maxFileSize 是单个文件大小 maxRequestSize是设

  • 我试图上传多个文件使用Spring mvc 4,Spring引导和thymeleaf作为模板引擎,但我无法访问上传的文件,文件被处理为一个多部分文件与内容类型的应用程序/octet-stream. 以及控制器代码: sysout的输出: 上传图像长度:1(即使我上传了多个文件) 文件原始名称(使用getOrialFileName): 文件名(使用getName):文件[] 文件大小: 0 文件内容

  • 问题内容: 我有一个200MB的文件,想通过下载提供给用户。但是,由于我们希望用户仅下载一次此文件,因此我们这样做: 强制下载。但是,这意味着整个文件必须加载到内存中,这通常不起作用。我们如何以每块kb的速度将文件流式传输给他们? 问题答案: 尝试这样的事情