当前位置: 首页 > 知识库问答 >
问题:

如何用restTemplate Spring-mvc发送多部分表单数据

沈冠宇
2023-03-14

我正在尝试用RestTemplate上传一个文件到带有Jetty的Raspberry Pi。在Pi上有一个运行的servlet:

protected void doPost(HttpServletRequest req, HttpServletResponse resp)
        throws ServletException, IOException {

    PrintWriter outp = resp.getWriter();

    StringBuffer buff = new StringBuffer();

    File file1 = (File) req.getAttribute("userfile1");
    String p = req.getParameter("path");
    boolean success = false;

    if (file1 == null || !file1.exists()) {
        buff.append("File does not exist\n");
    } else if (file1.isDirectory()) {
        buff.append("File is a directory\n");
    } else {
        File outputFile = new File(req.getParameter("userfile1"));
        if(isValidPath(p)){
            p = DRIVE_ROOT + p;
            final File finalDest = new File(p
                    + outputFile.getName());
            success = false;
            try {
                copyFileUsingFileChannels(file1, finalDest);
                finalDest.setWritable(true);
                success = true;
            } catch (Exception e) {
                e.printStackTrace();
            }
            if (success){
                buff.append("File successfully uploaded.\n");
            }
            else{
                                    buff.append("Failed to save file.");
            }
        }
        else{
            buff.append("Invalid path.\n");
        }
    }
    outp.write(buff.toString());
}
@ResponseBody 
@RequestMapping(value="/upload/",method=RequestMethod.POST ,produces = "text/plain")
public String uploadFile(MultipartHttpServletRequest request2, HttpServletResponse response2){

    Iterator<String> itr =  request2.getFileNames();

     MultipartFile file = request2.getFile(itr.next());
     System.out.println(file.getOriginalFilename() +" uploaded!");

    System.out.println(file.toString()); 
     MultiValueMap<String, Object> parts = new LinkedMultiValueMap<String, Object>();
    parts.add("userfile1",file);
    //reqEntity.addPart("userfile1", file);
    String path="/public/";
    RestTemplate restTemplate = new RestTemplate();
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.MULTIPART_FORM_DATA);
    System.out.println("1");
    HttpEntity<MultiValueMap<String, Object>> request = new HttpEntity<MultiValueMap<String, Object>>(parts, headers);
    String url =  url2+"/pi/GetFileServlet?path="+path;
    System.out.println("2");
/*  restTemplate.getMessageConverters().add(new FormHttpMessageConverter());
    restTemplate.getMessageConverters().add(
            new MappingJackson2HttpMessageConverter());*/
    System.out.println("3");
    ResponseEntity<String> response = restTemplate.exchange(url, HttpMethod.POST, request,String.class);
    System.out.println("4");
    System.out.println("response : " +response);
    if(response==null||response.getBody().trim()==""){
        return "error";
    }
    return response.getBody();
}

这是我得到的输出:

UI-elements.html已上传!

org.springframework.web.multipart.support.StandardMultipartTtpServletRequest$StandardMultipartFile@47e7673e

如您所见,数字4没有打印,在控制台中没有例外。调试期间发现的异常:

org.springframework.http.converter.HttpMessageNotWritableException: Could not write JSON: No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: org.springframework.web.multipart.support.StandardMultipartFile["inputStream"]); nested exception is com.fasterxml.jackson.databind.JsonMappingException: No serializer found for class java.io.ByteArrayInputStream and no properties discovered to create BeanSerializer (to avoid exception, disable SerializationFeature.FAIL_ON_EMPTY_BEANS) ) (through reference chain: org.springframework.web.multipart.support.StandardMultipartFile["inputStream"])

共有1个答案

牟波
2023-03-14

ByteArrayResource中读取整个文件可能是大文件的内存消耗问题。

您可以使用InputStreamResource在spring mvc控制器中代理文件上载:

@RequestMapping(value = "/upload", method = RequestMethod.POST)
public ResponseEntity<?> uploadImages(@RequestPart("images") final MultipartFile[] files) throws IOException {
    LinkedMultiValueMap<String, Object> map = new LinkedMultiValueMap<>();
    String response;
    HttpStatus httpStatus = HttpStatus.CREATED;

    try {
        for (MultipartFile file : files) {
            if (!file.isEmpty()) {
                map.add("images", new MultipartInputStreamFileResource(file.getInputStream(), file.getOriginalFilename()));
            }
        }

        HttpHeaders headers = new HttpHeaders();
        headers.setContentType(MediaType.MULTIPART_FORM_DATA);

        String url = "http://example.com/upload";

        HttpEntity<LinkedMultiValueMap<String, Object>> requestEntity = new HttpEntity<>(map, headers);
        response = restTemplate.postForObject(url, requestEntity, String.class);

    } catch (HttpStatusCodeException e) {
        httpStatus = HttpStatus.valueOf(e.getStatusCode().value());
        response = e.getResponseBodyAsString();
    } catch (Exception e) {
        httpStatus = HttpStatus.INTERNAL_SERVER_ERROR;
        response = e.getMessage();
    }

    return new ResponseEntity<>(response, httpStatus);
}

class MultipartInputStreamFileResource extends InputStreamResource {

    private final String filename;

    MultipartInputStreamFileResource(InputStream inputStream, String filename) {
        super(inputStream);
        this.filename = filename;
    }

    @Override
    public String getFilename() {
        return this.filename;
    }

    @Override
    public long contentLength() throws IOException {
        return -1; // we do not want to generally read the whole stream into memory ...
    }
}
 类似资料:
  • 这是在服务器端作为接收的内容: 如何转换multipart Confont数据类型中的文章对象?我读到改造可能允许使用转换器为这个。就我对文档的理解而言,它应该是实现的东西。 多部分部件使用的转换器,或者它们可以实现来处理自己的序列化。 null

  • 当我点击这个api时,我得到错误“415:Unsupported Media type”,这意味着不受支持的头。我想将文件从ARC加载到控制器。 我在pom.xml文件中添加了一些maven依赖项。 我的pom文件:

  • 不管怎么说,所有的想法和答案都是极其赞赏的。谢谢你的帮助。

  • 问题内容: 我试图发送某种形式而不重新加载页面,并且试图理解幕后细节,因此不使用任何JavaScript库: 调用了upload_file(),但如果我做对了,则不会发送数据。请提供有关发送数据的正确方式的建议。 问题答案: 通过表单传递属性 如果您想获得回覆,可以使用这个 您可以通过或检索所有数据 更新有点晚 至于有关上传的@Varun问题,此代码无法直接处理文件上传,要使用此代码发送文件,您需

  • 问题内容: 我们想将图像文件作为multipart / form发送到后端,我们尝试使用html表单获取文件并将文件作为formData发送,这是代码 后端中的错误是 “嵌套异常为org.springframework.web.multipart.MultipartException:无法解析多部分servlet请求;嵌套异常为java.io.IOException:org.apache.tomc

  • 您好,我想向邮递员发送一个带有json的正文和一个formd数据中的图像。。。 我将表单数据图像保存在s3桶中,实体具有作为图像链接的字符串属性 这里是我的spring boot控制器 我已经用@RequestParam和@RequestPart尝试了多部分文件。。。我收到以下错误: "不支持内容类型'multipart/form-data;边界=-------------------------