Перейти к основному содержимому

Загрузка файлов с помощью сервлетов и JSP

· 4 мин. чтения

1. Введение

В этом кратком руководстве мы увидим, как загрузить файл из сервлета.

Для этого мы сначала увидим ванильное решение Jakarta EE с возможностями загрузки файлов, предоставляемыми собственной аннотацией @MultipartConfig .

Затем мы рассмотрим библиотеку Apache Commons FileUpload для более ранних версий Servlet API.

2. Использование Jakarta EE @MultipartConfig

Jakarta EE поддерживает загрузку из нескольких частей.

Таким образом, это, вероятно, выбор по умолчанию при обогащении приложения Jakarta EE поддержкой загрузки файлов.

Во-первых, давайте добавим форму в наш HTML-файл:

<form method="post" action="multiPartServlet" enctype="multipart/form-data">
Choose a file: <input type="file" name="multiPartServlet" />
<input type="submit" value="Upload" />
</form>

Форма должна быть определена с использованием атрибута enctype="multipart/form-data" , чтобы сигнализировать о многокомпонентной загрузке.

Затем мы хотим аннотировать наш HttpServlet правильной информацией, используя аннотацию @MultipartConfig :

@MultipartConfig(fileSizeThreshold = 1024 * 1024,
maxFileSize = 1024 * 1024 * 5,
maxRequestSize = 1024 * 1024 * 5 * 5)
public class MultipartServlet extends HttpServlet {
//...
}

Затем давайте удостоверимся, что установлена наша папка загрузки сервера по умолчанию:

String uploadPath = getServletContext().getRealPath("") + File.separator + UPLOAD_DIRECTORY;
File uploadDir = new File(uploadPath);
if (!uploadDir.exists()) uploadDir.mkdir();

Наконец, мы можем легко получить наш входящий файл из запроса с помощью метода getParts() и сохранить его на диск:

for (Part part : request.getParts()) {
fileName = getFileName(part);
part.write(uploadPath + File.separator + fileName);
}

Обратите внимание, что в этом примере мы используем вспомогательный метод getFileName():

private String getFileName(Part part) {
for (String content : part.getHeader("content-disposition").split(";")) {
if (content.trim().startsWith("filename"))
return content.substring(content.indexOf("=") + 2, content.length() - 1);
}
return Constants.DEFAULT_FILENAME;
}

Для сервлета 3.1. В качестве альтернативы мы могли бы использовать метод Part.getSubmittedFileName() :

fileName = part.getSubmittedFileName();

3. Использование Apache Commons FileUpload

Если мы не работаем над проектом Servlet 3.0, мы можем напрямую использовать библиотеку Apache Commons FileUpload.

3.1. Настраивать

Мы будем использовать следующие зависимости pom.xml , чтобы запустить наш пример:

<dependency> 
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
<version>1.4</version>
</dependency>
<dependency>
<groupId>commons-io</groupId>
<artifactId>commons-io</artifactId>
<version>2.11.0</version>
</dependency>

Самые последние версии можно найти с помощью быстрого поиска в центральном репозитории Maven: commons-fileupload и commons-io .

3.2. Загрузить сервлет

Три основные части включения библиотеки Apache FileUpload выглядят следующим образом:

  • Форма загрузки на странице .jsp .
  • Настройка объекта DiskFileItemFactory и ServletFileUpload .
  • Обработка фактического содержимого загрузки составного файла.

Форма загрузки такая же, как и в предыдущем разделе.

Давайте перейдем к созданию нашего сервлета Jakarta EE.

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

Мы также укажем, какие ресурсы временно выделить для загрузки файла (во время обработки) на нашей DiskFileItemFactory.

Наконец, мы создадим объект ServletFileUpload , который будет представлять сам файл . Он предоставит содержимое многокомпонентной загрузки для окончательной серверной части сохранения:

if (ServletFileUpload.isMultipartContent(request)) {

DiskFileItemFactory factory = new DiskFileItemFactory();
factory.setSizeThreshold(MEMORY_THRESHOLD);
factory.setRepository(new File(System.getProperty("java.io.tmpdir")));

ServletFileUpload upload = new ServletFileUpload(factory);
upload.setFileSizeMax(MAX_FILE_SIZE);
upload.setSizeMax(MAX_REQUEST_SIZE);
String uploadPath = getServletContext().getRealPath("")
+ File.separator + UPLOAD_DIRECTORY;
File uploadDir = new File(uploadPath);
if (!uploadDir.exists()) {
uploadDir.mkdir();
}
//...
}

И затем мы можем извлечь это содержимое и записать его на диск:

if (ServletFileUpload.isMultipartContent(request)) {
//...
List<FileItem> formItems = upload.parseRequest(request);
if (formItems != null && formItems.size() > 0) {
for (FileItem item : formItems) {
if (!item.isFormField()) {
String fileName = new File(item.getName()).getName();
String filePath = uploadPath + File.separator + fileName;
File storeFile = new File(filePath);
item.write(storeFile);
request.setAttribute("message", "File "
+ fileName + " has uploaded successfully!");
}
}
}
}

4. Запуск примера

После того, как мы скомпилировали наш проект в .war , мы можем поместить его в наш локальный экземпляр Tomcat и запустить его.

Оттуда мы можем вызвать основное представление загрузки, где нам представлена форма:

./25076183673089abd01600e185f9d3fb.png

После успешной загрузки нашего файла мы должны увидеть сообщение:

./d6a54806ba6300e81c5a0306a2711ac5.png

Наконец, мы можем проверить местоположение, указанное в нашем сервлете:

./f436a2e9e2896195c1b658f5a99955df.png

5. Вывод

Вот и все! Мы узнали, как обеспечить загрузку файлов, состоящих из нескольких частей, с помощью Jakarta EE, а также с помощью библиотеки Apache Common FileUpload !

Фрагменты кода, как всегда, можно найти на GitHub .