SpringBoot: Large Streaming File Upload Using Apache Commons FileUpload

前端 未结 5 2214
萌比男神i
萌比男神i 2020-11-28 06:10

Am trying to upload a large file using the \'streaming\' Apache Commons File Upload API.

The reason I am using the Apache Commons File Uploader and not the default S

相关标签:
5条回答
  • 2020-11-28 06:39

    I use kindeditor + springboot. When I use (MultipartHttpServletRequest) request. I could get the file, but I use appeche-common-io:upload.parse(request) the return value is null.

    public BaseResult uploadImg(HttpServletRequest request,String type){
                    MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
                    MultiValueMap<String, MultipartFile> multiFileMap = multipartRequest.getMultiFileMap();
    
    0 讨论(0)
  • 2020-11-28 06:40

    Please try to add spring.http.multipart.enabled=false in application.properties file.

    0 讨论(0)
  • 2020-11-28 06:57

    Thanks to some very helpful comments by M.Deinum, I managed to solve the problem. I have cleaned up some of my original post and am posting this as a complete answer for future reference.

    The first mistake I was making was not disabling the default MultipartResolver that Spring provides. This ended up in the resolver processing the HttpServeletRequest and thus consuming it before my controller could act on it.

    The way to disable it, thanks to M. Deinum was as follows:

    multipart.enabled=false
    

    However, there was still another hidden pitfall waiting for me after this. As soon as I disabled default multipart resolver, I started getting the following error when trying to make an upload:

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

    In my security configuration, I had enabled CSRF protection. That necessitated that I send my POST request in the following manner:

    <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>
    

    I also modified my controller a bit:

    @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;
        }
    }
    

    where Response is just a simple generic response type I use:

    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
        ...
    }
    
    0 讨论(0)
  • 2020-11-28 06:58

    You Can simply add spring properties:

    spring.servlet.multipart.max-file-size=20000KB
    spring.servlet.multipart.max-request-size=20000KB
    

    here my maximum file size is 20000KB, you can change if required.

    0 讨论(0)
  • 2020-11-28 07:03

    If you're using a recent version of spring boot (I'm using 2.0.0.M7) then the property names have changed. Spring started using technology specific names

    spring.servlet.multipart.maxFileSize=-1

    spring.servlet.multipart.maxRequestSize=-1

    spring.servlet.multipart.enabled=false

    If you're getting StreamClosed exceptions caused by multiple implementations being active, then the last option allows you to disable the default spring implementation

    0 讨论(0)
提交回复
热议问题