File Upload via HTTP PUT Request

后端 未结 2 1170
半阙折子戏
半阙折子戏 2021-01-01 04:18

Does anyone have any idea of any products or libraries like Apache Commons FileUpload that will deal with PUT file uploads?

Any friendly advice or direction would be

相关标签:
2条回答
  • It is fairly painless to get spring to respond correctly to a File Upload request for an HTTP PUT Method.

    All it takes is overriding the isMultipart() method in a customized MultipartResolver class.

    import org.apache.commons.fileupload.FileUploadBase;
    import org.apache.commons.fileupload.servlet.ServletRequestContext;
    
    import javax.servlet.http.HttpServletRequest;
    
    public class PostAndPutCommonsMultipartResolver extends CommonsMultipartResolver {
    
        private static final String POST_METHOD = "POST";
        private static final String PUT_METHOD = "PUT";
    
        @Override
        public boolean isMultipart(HttpServletRequest request) {
    
            boolean isMultipartRequest = false;
    
            if (request != null) {
    
                if (POST_METHOD.equalsIgnoreCase(request.getMethod()) || PUT_METHOD.equalsIgnoreCase(request.getMethod())) {
    
                    isMultipartRequest = FileUploadBase.isMultipartContent(new ServletRequestContext(request));
                }
            }
    
            return isMultipartRequest;
        }
    }
    

    What is really important, is that the default MultipartResolver is extended so that the isMultipart() method will return a true for either a POST or PUT request.

    In general there are two default MultipartResolver implementations: CommonsMultipartResolver (used with Apache Commons FileUpload) and StandardServletMultipartResolver (used with Servlet 3.0+ Part API).

    Since we are using Apache Commons FileUpload we extended the CommonsMultipartResolver class.

    There is documentation on the MultipartResolver's Javadoc page that explains how to properly define a customized MultipartResolver for your application (emphasis added):

    There is no default resolver implementation used for Spring DispatcherServlets, as an application might choose to parse its multipart requests itself. To define an implementation, create a bean with the id "multipartResolver" in a DispatcherServlet's application context. Such a resolver gets applied to all requests handled by that DispatcherServlet.

    For an xml configured application it will look close to the following:

    <bean id="multipartResolver" class="<package>.<name>.PostAndPutCommonsMultipartResolver"/>
    

    For an annotation configured application it will look close to the following:

    @Bean(name = "multipartResolver")
    public CommonsMultipartResolver createMultipartResolver() {
        return new PostAndPutCommonsMultipartResolver();
    }
    

    More information on Annotation configuration of MultipartResolver.

    0 讨论(0)
  • 2021-01-01 04:35

    I'm not aware of any libraries that fulfill your requirements. But if you don't mind to do some coding, I think nice way to create something similar would be to write your own

    public class FileMessageConverter extends AbstractHttpMessageConverter<File> 
    

    that converts the request body to File in the tmp directory:

    @Override
    protected File readInternal(Class<? extends File> clazz, HttpInputMessage inputMessage)
            throws IOException, HttpMessageNotReadableException {
    
        InputStream inputStream = inputMessage.getBody();
        File tmpFile = File.createTempFile("upload","tmp");
        if (inputStream != null) {
            FileOutputStream outputStream = new FileOutputStream(tmpFile);
    
            byte[] buffer = new byte[1024];
            int bytesRead;
    
            while ((bytesRead = inputStream.read(buffer)) > 0) {
                outputStream.write(buffer, 0, bytesRead);
            }
    
            outputStream.flush();
    
            outputStream.close();
        }
        return tmpFile;
    }
    

    In the controller you would define your method with:

    @RequestMapping(value="/{fileName}", method = RequestMethod.PUT)
    public ResponseEntity uploadFile(@PathVariable(value="fileName") String fileName, @RequestBody File tmpFile) throws IOException {
    
        // .. process tmpFile, e.g. tmpFile.renameTo(new File(fileName);
        return new ResponseEntity<String>(HttpStatus.CREATED);
    }
    

    Don't forget to register your FileMessageConverter, e.g.

    @Configuration
    @EnableWebMvc
    @ComponentScan(basePackages =  {"my.controller.package"})
    public class WebConfig extends WebMvcConfigurerAdapter {
    
        @Override
        public void configureMessageConverters(List<HttpMessageConverter<?>> converters) {
            converters.add(new FileMessageConverter());
        }
    }
    

    The curl command to invoke the upload:

    curl -v -X PUT -T "myfile" http://localhost:8080/mytargetfilename
    
    0 讨论(0)
提交回复
热议问题