使用 Jersey 上传文件时设置文件大小限制

发布于 2024-12-14 21:55:41 字数 1191 浏览 3 评论 0原文

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

我的第一种方法是使用 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>

现在回答我的问题;如何使用 jersey 强制执行文件大小限制?一定有一些简单的方法,而不必将整个文件读入内存(ByteArray),然后获取实际大小,对吧?

I'm currently implementing functionality for uploading files using jersey rest. I would like to set a maximum allowed file size which to me seems like a pretty common requirement.

My first approach was to use Jerseys FormDataContentDisposition which should hold all the information I could possibly need about the file. But all information except the file name seems to be missing, including file size.

This is my rest method:

@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
}

Which isn't working since the returned size is always "-1"!

I use a extremely simple html form for the file upload:

<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>

So now to my question; how would you enforce a file size restriction using jersey? There must be some simple way without having to resort to reading the whole file into memory (ByteArray) and then get the actuall size, right?

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(5

山色无中 2024-12-21 21:55:41

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

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

If the client does not send the file size, fall back to reading the file from stream. Once you hit the size limit, stop reading and refuse the file. You should do this anyway, since you can't trust the client (anyone can create an app that sends http requests to your service and those requests may not have correct data you expect - so have to take that into account).

In addition, it may be possible to add some validation to the web form as well to fail fast, but I am not a JavaScript expert, so not sure if/how that can be done.

惜醉颜 2024-12-21 21:55:41

如果您使用的是 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 中?

If you're using tomcat you can set the
the size threshold at which the file will be written to the disk to a sensible value for your machine.

e.g. if the servlet is in 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>

or using annotations:

@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
)

With reference to HttpRequest maximum allowable size in tomcat?

墨洒年华 2024-12-21 21:55:41

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

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
}

You can check the length, in bytes, of the request body and made available by the input stream with the following code:

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

The key part being @Context final HttpServletRequest request. Then in the method body, you can get the length of the inputstream and react to it accordingly with:

int contentLength = request.getContentLength();

if (contentLength == -1 || contentLength > MAX_REQUEST_SIZE) {
  // deal with it
}
与君绝 2024-12-21 21:55:41

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

@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
}

You can get the request size by reading a header.
In your example:

@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
}
贪恋 2024-12-21 21:55:41

您可以让您的自定义类LimitedSizeInputStream扩展InputStream
使用 @Override 读取方法检查特定的大小限制,如 https://stackoverflow.com/a 中提到的/30072143/5962766。使用 new LimitedSizeInputStream(fileStream, FILE_SIZE_LIMIT) 包装您的 InputStream,当达到读取限制时,您将收到异常。

You can have your custom class LimitedSizeInputStream extends InputStream
with @Override read methods which check for specific size limit as mentioned on https://stackoverflow.com/a/30072143/5962766. Wrap your InputStream with new LimitedSizeInputStream(fileStream, FILE_SIZE_LIMIT) and you'll get exception when read limit is reached.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文