问题 使用Jersey上载文件时设置文件大小限制


我目前正在使用泽西休息实现上传文件的功能。我想设置一个允许的最大文件大小对我来说似乎是一个非常常见的要求。

我的第一种方法是使用Jerseys FormDataContentDisposition,它应该包含我可能需要的有关该文件的所有信息。但是除了文件名之外的所有信息似乎都缺失了,包括文件大小。

这是我的休息方法:

@POST
@Path("uploadFile/")
@Consumes("multipart/form-data")
@Produces("text/html")
public String handleDocumentUpload(
    @FormDataParam("file") InputStream uploadedInputStream,
    @FormDataParam("file") FormDataContentDisposition fileDetail)
{
    if(fileDetail.getSize() > MAX_FILE_SIZE)
    {
        throw new IllegalArgumentException(
                "File is to big! Max size is " + MAX_FILE_SIZE);
    }
    // ...more file handling logic
}

由于返回的大小始终为“-1”,因此无法正常工作!

我使用一个非常简单的html表单来上传文件:

<html>
  <head>
    <title>File upload</title>
  </head>
  <body>
 <p>Choose file</p>
 <form enctype="multipart/form-data" method="POST" action="uploadFile">
   <input type="file" name="file" size="50">
   <input type="submit" value="Upload">
 </form>
  </body>
</html>

那么现在问我的问题;你将如何使用泽西强制执行文件大小限制?必须有一些简单的方法,而不必诉诸于将整个文件读入内存(ByteArray),然后获得实际大小,对吧?


6258
2017-11-11 08:32


起源

只是为了澄清,除了不能限制文件大小外,它就像一个魅力。 - mattias_avelin
目前针对球衣2,以下帖子解决了这个问题 stackoverflow.com/questions/6301973/... - Indraneel


答案:


如果客户端未发送文件大小,则回退到从流中读取文件。达到大小限制后,停止阅读并拒绝该文件。无论如何,您应该这样做,因为您无法信任客户端(任何人都可以创建一个向您的服务发送http请求的应用程序,并且这些请求可能没有您期望的正确数据 - 因此必须考虑到这一点)。

此外,有可能在Web表单中添加一些验证以及快速失败,但我不是JavaScript专家,所以不确定是否/如何做到这一点。


5
2017-11-12 11:42



谢谢马丁!你当然是对的,我不应指望客户给我正确的文件大小。我们实现了它,以便如果客户端指定的文件大小> MAX_SIZE然后我们“快速失败”,否则我们读取流直到达到MAX_SIZE。我们没有找到在客户端验证文件大小的简单方法,因此必须这样做。再次感谢您的输入! - mattias_avelin
为了防止您的API接收不需要的HTTP调用,您可以创建一个CORS过滤器。 - russellhoff


如果你正在使用tomcat,你可以设置 文件将写入磁盘的大小阈值 为您的机器提供合理的价值。

例如如果servlet在web.xml中

<servlet>
  <servlet-name>Upload Servlet</servlet-name>
  <servlet-class>YourServletName</servlet-class>

  <multipart-config>
   <!-- 10MB of files -->
   <max-file-size>10485760</max-file-size>
   <!-- 10KB of form data -->
   <max-request-size>10240</max-request-size>
   <!-- Buffer to disk over 512KB -->
   <file-size-threshold>524288</file-size-threshold>
 </multipart-config>

</servlet>

或使用注释:

@MultipartConfig(
    maxFileSize=10485760,     // 10Mb max
    fileSizeThreshold=524288, //512 Kb before buffering to disk
    maxRequestSize=10240      // 10Kb of meta data
    location=/tmp             // with permission to write, default uses tomcat tmp
)

参考 HttpRequest在tomcat中允许的最大大小?


6
2018-03-27 07:47



以下 docs.oracle.com/javaee/7/tutorial/servlets011.htm 我会说max-file-size只适用于一个文件,max-request-size适用于整个请求(因此可能是多个文件和多部分)。 - Ondrej Burkert
JAX-RS / Jersey不使用MultipartConfig,因为它适用于Servlet而不是JAX-RS资源。 Jersey中的MultipartConfig没有等价物。请参阅 jersey.github.io/documentation/latest/media.html#multipart 详情。没有快速失败的解决方案。一个人不能依赖内容长度标题。我们要检查文件的大小,并在它大于预先设定的阈值时拒绝它。为什么那么可怕?想象一下,正在上传大量文件。 Jersey必须先将整个文件保存在磁盘上;如果服务器的磁盘空间有限,这不仅耗时而且不安全。 - Viswanath


您可以使用以下代码检查请求正文的长度(以字节为单位),并使输入流可用:

public Response uploadFile(@Context final HttpServletRequest request, @FormDataParam("uploadFile") InputStream uploadedInputStream,
      @FormDataParam("uploadFile") FormDataContentDisposition fileDetail, @FormDataParam("uploadFile") FormDataBodyPart body) {

关键部分是 @Context final HttpServletRequest request。然后在方法体中,您可以获得输入流的长度并对其做出相应的反应:

int contentLength = request.getContentLength();

if (contentLength == -1 || contentLength > MAX_REQUEST_SIZE) {
  // deal with it
}

2
2018-04-21 10:55





你可以拥有自定义 class LimitedSizeInputStream extends InputStream  同 @Override 读取检查特定大小限制的方法,如上所述 https://stackoverflow.com/a/30072143/5962766。包裹你的 InputStream 同 new LimitedSizeInputStream(fileStream, FILE_SIZE_LIMIT) 当达到读取限制时,您将获得异常。


0
2017-11-04 14:24





您可以通过阅读标题来获取请求大小。 在你的例子中:

@POST
@Path("uploadFile/")
@Consumes("multipart/form-data")
@Produces("text/html")
public String handleDocumentUpload(
    @HeaderParam("content-length") long contentLength,
    @FormDataParam("file") InputStream uploadedInputStream,
    @FormDataParam("file") FormDataContentDisposition fileDetail) {

    if(contentLength > MAX_FILE_SIZE) {
      throw new IllegalArgumentException(
            "File is to big! Max size is " + MAX_FILE_SIZE);
    }
  // ...more file handling logic
}

0
2018-03-23 14:03



内容长度可以捏造 - Somaiah Kumbera