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

如何在SpringMVC中使用多部分/表单和分块编码接收文件上载?

邹山
2023-03-14

我正在尝试编写一个SpringMVC方法,它可以接收多部分/表单或传输编码的分块文件上传。我可以编写一个单独的方法来处理每种类型,但我希望使用相同的方法,以便使用相同的REST POST uri,例如:

http://host:8084/attachments/testupload

以下是我迄今为止最好的尝试:

@RequestMapping(value = { "/testupload" }, method = RequestMethod.POST, produces = 
  "application/json")
public @ResponseBody
ResponseEntity<MessageResponseModel> testUpload(
  @RequestParam(value = "filedata", required = false) MultipartFile filedata,
  final HttpServletRequest request) throws IOException {

  InputStream is = null;
  if (filedata == null) {
    is = request.getInputStream();
  }
  else {
    is = filedata.getInputStream();
  }
  byte[] bytes = IOUtils.toByteArray(is);
  System.out.println("read " + bytes.length + " bytes.");

  return new ResponseEntity<MessageResponseModel>(null, null, HttpStatus.OK);
}

使用上述方法,我可以上传一个多部分文件,但如果我上传一个分块文件,我会从spring得到一个异常,它说:

org.springframework.web.multipart.MultipartException: \
The current request is not a multipart request

如果我删除MultipartFile请求参数,它非常适合分块传输编码。如果我离开它在它的作品伟大的MultipartFile上传。如何使用相同的方法处理两种上传类型?

这适用于块:

@RequestMapping(value = { "/testupload" }, method = RequestMethod.POST, produces = 
  "application/json")
public @ResponseBody
ResponseEntity<MessageResponseModel> testUpload(
  final HttpServletRequest request) throws IOException {

  InputStream is = null;
  is = request.getInputStream();
  byte[] bytes = IOUtils.toByteArray(is);
  System.out.println("read " + bytes.length + " bytes.");

  return new ResponseEntity<MessageResponseModel>(null, null, HttpStatus.OK);
}

这对于MultipartFile非常有效:

@RequestMapping(value = { "/testupload" }, method = RequestMethod.POST, produces = 
  "application/json")
public @ResponseBody
ResponseEntity<MessageResponseModel> testUpload(
  @RequestParam MultipartFile filedata) throws IOException {

  InputStream is = null;
  is = filedata.getInputStream();
  byte[] bytes = IOUtils.toByteArray(is);
  System.out.println("read " + bytes.length + " bytes.");

  return new ResponseEntity<MessageResponseModel>(null, null, HttpStatus.OK);
}

这应该是可能的,有人知道怎么做吗?

谢谢你,史蒂夫

共有2个答案

笪欣嘉
2023-03-14

这是控制器

package com.faisalbhagat.web.controller;

@Controller
@RequestMapping(value = { "" })
public class UploadController {

    @RequestMapping(value = "/uploadMyFile", method = RequestMethod.POST)
    @ResponseBody
    public String handleFileUpload(MultipartHttpServletRequest request)
            throws Exception {
        Iterator<String> itrator = request.getFileNames();
        MultipartFile multiFile = request.getFile(itrator.next());
                try {
            // just to show that we have actually received the file
            System.out.println("File Length:" + multiFile.getBytes().length);
            System.out.println("File Type:" + multiFile.getContentType());
            String fileName=multiFile.getOriginalFilename();
            System.out.println("File Name:" +fileName);
            String path=request.getServletContext().getRealPath("/");

            //making directories for our required path.
            byte[] bytes = multiFile.getBytes();
            File directory=    new File(path+ "/uploads");
            directory.mkdirs();
            // saving the file
            File file=new File(directory.getAbsolutePath()+System.getProperty("file.separator")+picture.getName());
            BufferedOutputStream stream = new BufferedOutputStream(
                    new FileOutputStream(file));
            stream.write(bytes);
            stream.close();
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
            throw new Exception("Error while loading the file");
        }
        return toJson("File Uploaded successfully.")
    }

    public String toJson(Object data)
    {
        ObjectMapper mapper=new ObjectMapper();
        StringBuilder builder=new StringBuilder();
        try {
            builder.append(mapper.writeValueAsString(data));
        } catch (Exception e) {
            // TODO Auto-generated catch block
            e.printStackTrace();
        }
        return builder.toString();
    }
}

您可以在中找到复杂的解决方案,客户端代码位于http://faisalbhagat.blogspot.com/2014/09/springmvc-fileupload-with-ajax-and.html

孟承嗣
2023-03-14

摘录自我的代码(Spring 3.2,用AngularJS上传的Blueimp文件):

/**
 * Handles chunked file upload, when file exceeds defined chunked size.
 * 
 * This method is also called by modern browsers and IE >= 10
 */
@RequestMapping(value = "/content-files/upload/", method = RequestMethod.POST, headers = "content-type!=multipart/form-data")
@ResponseBody
public UploadedFile uploadChunked(
        final HttpServletRequest request,
        final HttpServletResponse response) {

    request.getHeader("content-range");//Content-Range:bytes 737280-819199/845769
    request.getHeader("content-length"); //845769
    request.getHeader("content-disposition"); // Content-Disposition:attachment; filename="Screenshot%20from%202012-12-19%2017:28:01.png"
    request.getInputStream(); //actual content.

    //Regex for content range: Pattern.compile("bytes ([0-9]+)-([0-9]+)/([0-9]+)");
    //Regex for filename: Pattern.compile("(?<=filename=\").*?(?=\")");

    //return whatever you want to json
    return new UploadedFile();
}

/**
 * Default Multipart file upload. This method should be invoked only by those that do not
 * support chunked upload.
 * 
 * If browser supports chunked upload, and file is smaller than chunk, it will invoke
 * uploadChunked() method instead.
 * 
 * This is instead a fallback method for IE <=9
 */
@RequestMapping(value = "/content-files/upload/", method = RequestMethod.POST, headers = "content-type=multipart/form-data")
@ResponseBody
public HttpEntity<UploadedFile> uploadMultipart(
        final HttpServletRequest request,
        final HttpServletResponse response,
        @RequestParam("file") final MultipartFile multiPart) {

    //handle regular MultipartFile

    // IE <=9 offers to save file, if it is returned as json, so set content type to plain.
    HttpHeaders headers = new HttpHeaders();
    headers.setContentType(MediaType.TEXT_PLAIN);
    return new HttpEntity<>(new UploadedFile(), headers);
}

这应该能让你开始。在IE8、IE9、IE10、Chrome、FF上进行的最小测试。当然可能会有问题,可能有一个更简单的方法来提取内容范围,但是...对我有效。

 类似资料:
  • 我正在尝试使用Support Bee API创建附件,如下所述:https://supportbee.com/api#create_attachment 我编写了一个服务,它使用创建并发送使用文件名的请求。 如果我在《邮递员》中测试,它会成功。我正在为正文使用,只是从UI中选择要上载的文件: 当我试图通过我的服务上传它时,它不起作用: 这将导致500内部服务器错误。检查对象时,我可以看到它的标题值

  • 我想在API正文中以多部分形式发送以下POST请求: 上传传递两个属性(KEY)和(VALUE)发送arquivo(KEY)和(file)如何使用REST-Assured实现这一点 多部分打印https://ibb.co/0QQCkQv 尝试:

  • 问题内容: 我是angular.js的初学者,但是对基础知识有很好的了解。 我要做的是上传文件和一些表单数据作为多部分表单数据。我读到这不是angular的功能,但是3rd party库可以做到这一点。我已经通过git克隆了angular-file-upload,但是仍然无法发布简单的表单和文件。 有人可以提供如何执行此操作的示例,html和js吗? 问题答案: 首先 您无需对结构进行任何特殊更改

  • 我已经看到有关于如何使用多部分形式(https://github.com/reactor/reactor-netty/blob/89796a1839a1439a1800424e130515357a827392/src/test/java/reactor/netty/http/client/HttpClientTest.java#L337)发布文件的反应器网的例子 但是我找不到任何关于如何使用rep

  • 我正在编写一个Go客户端,通过REST-API创建备份。带有多部分表单数据的REST-API响应到GET请求。因此,响应(类型*http.response)正文的内容如下: 如何从响应正文中提取zip文件? 我试图使用内置(net / http)方法,但这些方法需要一个请求结构。

  • 我需要实现一个RESTendpoint,它接收我使用的多部分/表单数据: Spring防尘套 科特林 SpringMVC 提交包含以下部分的多部分表单: 部署名称------文本/普通 启用重复筛选------文本/普通 仅更改部署------文本/普通 部署源------文本/普通 租户id------文本/普通 *----应用程序/八位字节流 Rest控制器看起来是这样的: 对于所有有效的参数