Установка ограничений размера файла при загрузке файлов в Джерси

В настоящее время я реализую функциональность для загрузки файлов с использованием трикотажа. Я хотел бы установить максимально допустимый размер файла, который для меня кажется довольно распространенным требованием.

Мой первый подход заключался в использовании триггеров 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), а затем получить размер актуала, правильно?

Ответ 1

Если клиент не отправляет размер файла, вернитесь к чтению файла из потока. Как только вы нажмете ограничение по размеру, прекратите чтение и откажитесь от файла. Вы все равно должны это делать, так как вы не можете доверять клиенту (любой может создать приложение, которое отправляет http-запросы вашей службе, и эти запросы могут не иметь правильных данных, которые вы ожидаете, - так что имейте это в виду).

Кроме того, может быть возможно добавить некоторую проверку в веб-форму, а также быстро выйти из строя, но я не эксперт по JavaScript, поэтому не уверен, что/как это можно сделать.

Ответ 2

Если вы используете tomcat, вы можете установить порог размера, при котором файл будет записан на диск, до разумного значения для вашего компьютера.

например. если сервлет находится в 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?

Ответ 3

Вы можете проверить длину в байтах тела запроса и сделать доступным входной поток со следующим кодом:

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
}

Ответ 4

У вас может быть ваш пользовательский class LimitedSizeInputStream extends InputStream с помощью методов @Override, которые проверяют ограничение по конкретному размеру, как указано в fooobar.com/questions/525191/.... Оберните InputStream с помощью new LimitedSizeInputStream(fileStream, FILE_SIZE_LIMIT), и вы получите исключение, когда достигнут предел чтения.

Ответ 5

Вы можете получить размер запроса, прочитав заголовок. В вашем примере:

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