Java SpringREST:通过rest控制器上传大文件(1GB)

Java SpringREST:通过rest控制器上传大文件(1GB),java,spring,rest,multipartform-data,Java,Spring,Rest,Multipartform Data,[上下文:java 8,spring boot 1.5.1] 我们正在创建一个RESTful服务,我们需要能够上传大文件。我想要的是一个类似这样的api @RequestLine("POST /object") @Headers("Content-Type: multipart/form-data") void create(InputStreamResource resource, ...); 我不想使用MultipartFile读取整个文件,也不想使用HttpServletRequest,

[上下文:java 8,spring boot 1.5.1]

我们正在创建一个RESTful服务,我们需要能够上传大文件。我想要的是一个类似这样的api

@RequestLine("POST /object")
@Headers("Content-Type: multipart/form-data")
void create(InputStreamResource resource, ...);
我不想使用
MultipartFile
读取整个文件,也不想使用
HttpServletRequest
,因为它似乎不属于这里,而是需要某种
HttpMessageConverter
。话虽如此,使用一个
HttpServletRequest
我可以解决如下问题

ServletFileUpload upload = new ServletFileUpload();
FileItemIterator iterator = upload.getItemIterator(request);
while (iterator.hasNext()) {
  FileItemStream e = iterator.next();
  if (!e.isFormField()) {
    InputStream inputStream = item.openStream();
    //...
  }
}
理想情况下,我想要一个
InputStream
或包装它的东西,例如
InputStreamResource
(如上所示)


如果有任何建议,我们将不胜感激。

我就是这样做的,这似乎是处理上传而不使用临时文件或使用@RequestBody注释将文件读入字节数组的唯一方法,正如stackoverflow.com在一个线程中建议的那样:

@RequestMapping("firmware/{firmwareId:\\d+}/logs/upload")
public
@ResponseBody
ResponseEntity handleUploadLogs(@PathVariable("firmwareId") final Long firmwareId, final HttpServletRequest request) {
    try (final InputStream is = getInputStream(request)) {
        if (is != null) {
            firmwareContentService.uploadLogs(firmwareId, is);

            return ok().build();
        } else {
            return badRequest().build();
        }
    } catch (IOException | FileUploadException e) {
        return badRequest().build();
    }
}

private InputStream getInputStream(final HttpServletRequest request) throws IOException, FileUploadException {
    final ServletFileUpload upload = new ServletFileUpload();
    final FileItemIterator iterator = upload.getItemIterator(request);

    InputStream is = null;

    while (iterator.hasNext()) {
        final FileItemStream item = iterator.next();

        if (!item.isFormField()) {
            is = item.openStream();

            break;
        }
    }

    return is;
}
更新


这个简单的代码也适用于我。只需将InputStream放入方法参数:

@PostMapping("firmware/{firmwareId:\\d+}/logs/upload")
public
@ResponseBody
ResponseEntity handleUploadLogs(@PathVariable("firmwareId") final Long firmwareId, final InputStream is) {
    try {
        firmwareContentService.uploadLogs(firmwareId, is);

        return ok().build();
    } catch (IOException e) {
        return badRequest().build();
    }
}


上面的“简单代码”实际上不起作用。方法参数中的InputStream包含整个http请求。

谢谢,Igor。不幸的是,我在最初的帖子中已经描述了你的解决方案(如果不清楚,我很抱歉)。我的帖子的关键是我不想要一个
HttpServletRequest
(或者
MultipartFile
),例如
ResponseEntity handleUploadLogs(最终的HttpServletRequest请求)
,因为我想要一个干净的API,我更希望有一个
InputStream
或一个封装一个API的POJO。例如,如果我们采取相反的情况,下载一个文件,我不需要传递
HttpServletResponse
来写入它的OutputStream,我只需要返回一个
ResponseEntity
,就可以对请求的对象进行流式处理。只需将InputStream放入方法参数中。不知怎么的,它对我起了作用。谢谢,伊戈尔——它很有魅力。我以为你需要使用
资源
包装器,但这不是必需的-
无效创建(InputStream in…)
是我所需要做的全部。对不起,Igor,在我接受之前,我不得不做更多的测试,现在看来我说得太早了:(…InputStream的内容[a]spring传入的方法调用与您自己使用java API[B]读取文件不同。例如,获取一个小图像,将两个流[a&B]]读入字节数组并比较内容。此外,当我将内容[a]保存到磁盘时,我无法将其作为图像文件打开。您是否遵循?