При разработке системы веб -приложений функции загрузки файлов и загрузки являются очень часто используемыми функциями. Сегодня давайте поговорим о реализации функций загрузки и загрузки файлов в Javaweb.
Для загрузки файлов браузер передает файл на сервер в форме потока в процессе загрузки. Это более хлопотно, если вы напрямую используете Сервлет для получения входного потока загруженного файла, а затем анализировать в нем параметры запроса. Следовательно, он обычно выбирается для использования общей загрузки, компонента загрузки файла инструмента Apache Open Source. Пакет JAR с компонентом загрузки обычной загрузки может быть загружен на официальном веб-сайте Apache, или его можно найти в папке Lib of Struts. Функция загрузки стойки основана на этой реализации. Common-FileUpload зависит от пакета Common-IO, поэтому вам также необходимо загрузить этот пакет.
1. Строительство развития
Создайте проект FileUploadandDownload и добавьте пакет JAR-компонента Apache's Commons-FileUpload, связанный с компонентом, как показано на рисунке ниже:
2. Реализация загрузки файла
2.1. Страница загрузки файла и страница подсказки сообщения
Код страницы upload.jsp выглядит следующим образом:
<%@ page language = "java" pageencoding = "utf-8"%> <! Doctype html> <html> <head> <tite> upload file </title> </head> <body> <form action = "$ {pagecontext.request.contextpath}/servlet/uploadhounderververververververververververververververververververververververever intemptaRt. Пользователь: <input type = "text" name = "username"> <br/> Файл загрузки 1: <input type = "file" file1 "> <br/> файл загрузки 2: <input type =" file "name =" file2 "> <br/> <input type =" Отправить "value =" Отправить "> </form> </body> </html>. Печать?2.2. Обработка сервлет для загрузки файлов
Код uploadhandleservlet заключается в следующем:
Пакет me.gacl.web.controller; Импорт java.io.file; Импорт java.io.fileOutputStream; импортировать java.io.ioexception; импортировать java.io.inputstream; импортировать java.util.list; Импорт javax.servlet.servletexception; Импорт javax.servlet.http.httpservlet; Импорт javax.servlet.http.httpservletrequest; Импорт javax.servlet.http.httpservletresponse; Импорт org.apache.commons.fileupload.fileitem; Import org.apache.commons.fileupload.disk.diskfileitemfactory; Import org.apache.commons.fileupload.servlet.servletfileUpload; открытый класс uploadhandleservlet расширяет httpservlet {public void doget (httpservlectrequest, httpservletresponse response). this.getServletContext (). getRealPath ("/web-inf/upload"); File file = new File (savePath); // Существует ли сохраненный каталог загруженного файла, if (! File.exists () &&! File.isdirectory ()) {System.out.println (SavePath+"Directory не существует, его необходимо создать"); // Создать файл каталога.mkdir (); } // Сообщение подсказывает string message = ""; Попробуйте {// Использовать компонент загрузки файла Apache для обработки шагов загрузки файла: // 1. Создать DiskFileItemFactory Factory DiskFileItemfactory Factory = new DiskFileItemFactory (); // 2. Создать файл загрузки анализатора ServletFileUpload upload = new ServletFileUpload (Factory); // Решить китайский искаженную upload.setheAderencoding ("UTF-8"); // 3. Определите, являются ли представленные данные данными формы загрузки if (! Servletfileupload.ismultipartContent (request)) {// Получить данные возврата традиционным способом; } // 4. Используйте анализатор ServletFileUpload, чтобы анализировать загруженные данные. Результат анализа возвращает коллекцию списка <FieleItem>. Каждый FileItem соответствует элементу ввода списка форм формы <FieleItem> list = upload.parserequest (request); Для (FileItem Item: List) {// Если данные обычного ввода элемента инкапсулируются в файле fileItem if (item.isformfield ()) {string name = item.getfieldname (); // Решить китайскую искаженную проблему данных об обычных входных элементах string value = item.getString ("UTF-8"); // value = new String (value.getBytes ("iso8859-1"), "UTF-8"); System.out.println (name + "=" + value); } else {// Если элемент файла инкапсуляет загруженный файл // Получить загруженное имя файла, string fileName = item.getName (); System.out.println (имя файла); if (filename == null || filename.trim (). equals ("")) {продолжение; } // Примечание: имена файлов, представленные разными браузерами, разные. Некоторые браузеры отправляют файлы с путями, такими как: c: /a/b/1.txt, а некоторые - просто простые имена файлов, такие как: 1.txt // Обработать часть пути файла имени полученного загруженного файла, только часть файла имени файла сохраняется filename = filename.substring (filename.lastidexof ("//")+1); // Получить поток ввода загруженного файла в элементе inputStream in = item.getInputStream (); // Создать файл выходной потоки FileOutputStream OUT = new FileOutputStream (savePath + "//" + filename); // создать буферный байтовый буфер [] = новый байт [1024]; // Идентификация того, были ли данные в входном потоке, прочитаны int len = 0; // Входной поток считывается в цикл буфера, (len = in.read (buffer))> 0 означает, что все еще есть данные в while ((len = in.read (buffer))> 0) {// Использование выходного потока FileOutputStream, чтобы записать данные буфера в указанный каталог (SavePath + "//" + fileName Out.write (Buffer, 0, len); } // Закрыть входной поток в .close (); // закрыть выходной поток out.close (); // Удалить временный файл, сгенерированный при обработке файла item.delete (); Message = "Загрузка файла была успешно загружена!"; }}}} catch (Exception e) {message = "Загрузка файла не удалась!"; e.printstacktrace (); } request.setattribute ("Сообщение", сообщение); request.getRequestDispatcher ("/message.jsp"). } public void Dopost (httpservletRequest, httpservletresponse response) Throws ServletException, ioException {Doget (запрос, ответ); }}Зарегистрировать uploadhandleservlet в файле web.xml
<servlet> <servlet-name> uploadhandleservlet </servlet-name> <verlet-class> me.gacl.web.controller.uploadhandleervlet </servlet-class> </servlet> <servlet-mapping> <servlet-name> uploadhandleservlet </servlet-name> <url-pattern>/servlet/uploaderververvelt </servlet-name> <urll-pattern>/upletradervervelt (/servlet-pathernervlet </servlet-pathervlet </servlet-pathervlet </servlet-mapping>
Эффект работы заключается в следующем:
После успешной загрузки файла загруженный файл сохраняется в каталоге загрузки в каталоге Web-Inf, как показано на рисунке ниже:
2.3. Подробная информация о загрузке файлов
Хотя приведенный выше код может успешно загружать файлы в указанный каталог на сервере, существует много мелких деталей, которые необходимо обратить внимание на функцию загрузки файла. На следующие моменты следует уделять особое внимание.
1. Чтобы обеспечить безопасность сервера, загрузки файлы должны быть помещены в каталог, который не может быть доступен непосредственно в внешнем мире, например, в каталоге Web-Inf.
2. Чтобы предотвратить перезапись файла, для загрузки файла должно быть сгенерировано уникальное имя файла.
3. Чтобы предотвратить появление слишком большого количества файлов в каталоге, вы должны использовать хэш -алгоритм, чтобы разбить хранилище.
4. Максимальное значение загруженных файлов должно быть ограничено.
5. Чтобы ограничить тип загруженных файлов при получении загруженного имени файла, определите, является ли имя суффикса законным.
В ответ на вышеупомянутые 5 подробных вопросов, давайте улучшим загрузку HandleServlet. Улучшенный код заключается в следующем:
Пакет me.gacl.web.controller; Импорт java.io.file; Импорт java.io.fileOutputStream; импортировать java.io.ioexception; импортировать java.io.inputstream; импортировать java.util.list; импортировать java.util.uuid; Импорт javax.servlet.servletexception; Импорт javax.servlet.http.httpservlet; Импорт javax.servlet.http.httpservletrequest; Импорт javax.servlet.http.httpservletresponse; Импорт org.apache.commons.fileupload.fileitem; Import org.apache.commons.fileupload.fileuploadbase; Import org.apache.commons.fileupload.progresslistener; Import org.apache.commons.fileupload.disk.diskfileitemfactory; Import org.apache.commons.fileupload.servlet.servletfileUpload; / ** * @classname: uploadhandleservlet * @description: todo (я использую одно предложение, чтобы описать функцию этого класса) * @author: гарантия canglang * @date: 2015-1-3 11:35:50 * */ public class uploaderservlet extends httpservlet {public void represservlet, httpservlet httpservl ServletException, ioException {// Получить сохраненный каталог загруженного файла, хранить загруженный файл в каталоге Web-Inf и не позволяет прямую доступ к внешнему миру, чтобы обеспечить безопасность загруженных файлов string savePath = this.getServletContext (). GetRealPath («/web-inf/upload»); // Временный файл, сгенерированный во время загрузки, сохраняется с помощью строки каталогов Temppath = this.getServletContext (). GetRealPath ("/web-inf/temp"); File tmpfile = new File (Temppath); if (! tmpfile.exists ()) {// Создать временный каталог tmpfile.mkdir (); } // Сообщение подсказывает string message = ""; "; Попробуйте {// Использовать компонент загрузки файла Apache для обработки шагов загрузки файла: // 1. Создать DiskFileItemFactory Factory DiskFileItemfactory Factory = new DiskFileItemFactory (); // Установите размер буфера завода. Когда размер загруженного файла превышает размер буфера, временный файл будет создан и сохранен в указанном временном каталоге. factory.setsizethershold (1024*100); // Установить размер буфера на 100 КБ. Если не указано, размер буфера по умолчанию составляет 10 КБ. // Установить каталог хранилища временного файла, сгенерированного во время загрузки Factory.setRepository (tmpfile); // 2. Создать файл загрузки анализатора ServletFileUpload upload = new ServletFileUpload (Factory); // прослушивание загрузки файлов overload upload.setprogresslistener (new ProgressListener () {public void update (long pbytesread, long pcontentlength, int arg2) {System.out.println («Размер файла:« + pcontentlength + », в настоящее время обработан:« + pbytesread); /** Размер файла: 14608, в настоящее время обработано: « + pbytesread); /** Обработано: 7367 Размер файла: 14608, в настоящее время обрабатывается: 11419 Размер файла: 14608, в настоящее время обрабатывается: 14608 */}}); // Решить китайский искаженную upload.setheAderencoding ("UTF-8"); // 3. Определите, являются ли представленные данные данными формы загрузки if (! Servletfileupload.ismultipartContent (request)) {// Получить данные возврата традиционным способом; } // Установить максимальное значение размера загруженного отдельного файла, который в настоящее время устанавливается на 1024*1024 байт, то есть 1 МБ upload.setFilesizeMax (1024*1024); // Установите максимальное значение общего количества загруженных файлов, максимальное значение = сумма максимальных размеров нескольких файлов, загруженных одновременно, что в настоящее время установлено на 10 МБ. // 4. Используйте анализатор ServletFileUpload, чтобы анализировать загруженные данные. Результат анализа возвращает коллекцию списка <FieleItem>, каждый FileItem соответствует элементу ввода списка формы формы <FieleItem> list = upload.parserequest (request); Для (FileItem Item: List) {// Если FileItem инкапсулирует данные обычных элементов ввода if (item.isformfield ()) {string name = item.getfieldname (); // Решает китайскую искаженную проблему данных об обычных входных элементах string value = item.getString ("utf-8"); // value = new String (value.getBytes ("iso8859-1"), "UTF-8"); System.out.println (name + "=" + value); } else {// Если FileItem инкапсулирует загруженный файл // Получить загруженное имя файла, string fileName = item.getName (); System.out.println (имя файла); if (filename == null || filename.trim (). equals ("")) {продолжение; } // Примечание: имена файлов, представленные разными браузерами, разные. Некоторые браузеры отправляют имена файлов с путями, такими как: c: /a/b/1.txt, в то время как некоторые являются просто простыми именами файлов, такие как: 1.txt // Обработайте часть пути имени файла полученного загруженного файла, только часть файла имени файла сохраняется filename = filename.substring (filename.lastidexof ("//")+1); // Получить расширение загруженного файла string fileextname = filename.substring (fileName.lastIndexof (".")+1); // Если вам нужно ограничить загруженный тип файла, вы можете использовать расширение файла, чтобы определить, является ли загруженный тип файла Legal System.out.println («Расширение загруженного файла:«+fileExtName); // Получить поток ввода загруженного файла в элементе inputStream in = item.getInputStream (); // Получить имя файла Сохраняемого строки saveFilename = MakeFilename (FileName); // Получить файл сохранение string realSavePath = makePath (saveFilename, savePath); // Создать файл выходной потоки FileOutputStream OUT = new FileOutputStream (RealSavePath + "//" + saveFilename); // создать буферный байтовый буфер [] = новый байт [1024]; // Идентификация определения того, были ли данные в входном потоке считываются int len = 0; // Входной поток считывается в буфере, (len = in.read (buffer))> 0 означает, что все еще есть данные в while ((len = in.read (buffer))> 0) {// Использовать выходной поток выходного сигнала для записи данных буфера в указанный каталог (savePath + "//" + fileName) Out (Buffer, 0, 0, Len); } // Закрыть входной поток в .close (); // закрыть выходной поток out.close (); // Удалить временный файл, сгенерированный при обработке файла загрузки //item.delete (); Message = "Загрузка файла была успешно загружена!"; }}} catch (fileUploadBase.filesizeLimitexedException e) {e.printstackTrace (); request.setattribute («Сообщение», «Максимальное значение одного файла превышено !!!»); request.getRequestDispatcher ("/message.jsp"). возвращаться; } catch (fileUploadBase.sizelimitexedEdexception e) {e.printstackTrace (); request.SetAttribute («Сообщение», «Общий размер загруженного файла превышает максимальное значение предела !!!»); request.getRequestDispatcher ("/message.jsp"). возвращаться; } catch (Exception e) {message = "Загрузка файла не удалась!"; e.printstacktrace (); } request.setattribute ("Сообщение", сообщение); request.getRequestDispatcher ("/message.jsp"). } /*** @method: makefilename* @description: сгенерировать имя файла загруженного файла с именем файла as: uuid+ "_"+ исходное имя файла* @anthor: 发官网* @param filenam // Чтобы предотвратить перезапись файла, для загрузки файла должно быть сгенерировано уникальное имя файла. Return uuid.randomuuid (). ToString () + "_" + файл; } / *** Чтобы предотвратить появление слишком большого количества файлов в каталоге, вам необходимо использовать хэш -алгоритм, чтобы разбить хранилище* @method: MakePath* @Description:* @anthor: одинокий и амортирующий волк** @param fileName имени файла, создание каталогов хранилища на основе файла nemport -striptor -new -string -string -strise strishory strishory @trator @ret @ret @ret @ret @ret @ret @ret @ret @trator @ret @ret @ret @trator @ret @ret @trator @ret @tre @tre @trator FileName, String SavePath) {// Получить значение хэшкода имени файла и то, что вы получаете, является адресом имени файла объекта String в памяти int hashcode = filename.hashcode (); int dir1 = hashcode & 0xf; // 0--15 int dir2 = (hashcode & 0xf0) >> 4; // 0-15 // Создание новой строки каталога сохранения dir = savePath + "//" + dir1 + "//" + dir2; // upload/2/3 upload/3/5 // Файл может представлять файл файла и файл каталога = новый файл (dir); // Если каталог не существует, если (! File.exists ()) {// Создать файл каталога.mkdirs (); } return dir; } public void Dopost (httpservletRequest, httpservletresponse response) Throws ServletException, ioException {Doget (запрос, ответ); }}После улучшения вышеупомянутых пяти мелких деталей наша функция загрузки файла была относительно полной.
3. Скачать файл
3.1. Перечислите файловые ресурсы, предоставленные для загрузки
Мы хотим предоставить пользователям файловые ресурсы в системе веб -приложений для загрузки. Во -первых, нам нужно иметь страницу для перечисления всех файлов в загруженном каталоге файлов. Когда пользователь нажимает на загрузку файла Hyperlink, он будет загружен и напишет ListFileServlet, чтобы перечислить все загруженные файлы в системе веб -приложений.
Код Listfileservlet заключается в следующем:
Пакет me.gacl.web.controller; Импорт java.io.file; импортировать java.io.ioexception; импортировать java.util.hashmap; импортировать java.util.map; Импорт javax.servlet.servletexception; Импорт javax.servlet.http.httpservlet; Импорт javax.servlet.http.httpservletrequest; Импорт javax.servlet.http.httpservletresponse; / ** * @classname: listfileservlet * @description: списки всех загруженных файлов в веб-системе * @author: ganuarte * @date: 2015-1-4 9:54:40 * *// public class listfileservlet extpservsevsev // Получить каталог для загрузки файлов string uploadfilepath = this.getServletContext (). GetRealPath ("/web-inf/upload"); // Хранение имени файла для загрузки карты <string, string> filenamemap = new hashmap <string, string> (); // Рекурсивно пройти все файлы и каталоги в каталоге FILEPATH и сохранить имя файла файла в списке списков карт (новый файл (uploadFilePath), filenamemap); // Файл может представлять либо файл, либо каталог // Отправить коллекцию карты на страницу listfile.jsp для отображения request.setTtribute ("filenAmemap", filLenAmemememememememAp; request.getRequestDispatcher ("/listfile.jsp"). } /*** @method: listfile* @description: рекурсивно пройти все файлы в указанном каталоге* @anthor: 光克* @param if (! file.isfile ()) {// Перечислите все файлы и каталоги в файлах каталога [] = file.listfiles (); // Передача файлов [] массив для (файл f: файлы) {// рекурсивный список списков (f, map); }} else { /*** Обработайте имя файла. Загруженный файл переименован в форме имени uuid_file. Удалите часть uuid_ часть файла файла файла file.getName (). Indexof ("_"), чтобы получить местоположение символа "_" в строке. Если имя файла аналогично: 9349249849-88343-8344_a_fan_davi.avi, то File.getName (). Substring (file.getName (). Indexof ("_")+1) может получить a_fan_davi.avi part*/ string reallaname =+1). file.getName (). substring (file.getName (). indexof ("_")+1); //file.getName () получает исходное имя файла. Это имя уникально, поэтому его можно использовать в качестве ключа. RealName - это обработанное имя. Это может быть повторено map.put (file.getName (), realName); }} public void dopost (httpservletrequest -запрос, httpservletresponse response) throws servletexception, ioexception {Doget (запрос, ответ); }} Здесь я кратко рассказываю о методе списки в списке Fileservlet. Метод списков используется для перечисления всех файлов в каталоге. Метод списка использует рекурсию. В реальной разработке мы обязательно создадим таблицу в базе данных, в которой хранится загруженное имя файла и конкретный каталог хранилища файла. Мы можем знать конкретный каталог хранилища файла, запрашивая таблицу, и нет необходимости использовать рекурсионные операции. Этот пример заключается в том, что база данных не хранит загруженное имя файла и конкретное местоположение хранилища файла, а место для хранения загруженного файла используется для разрушения хранилища, поэтому необходима рекурсия. Во время рекурсии полученное имя файла хранится в коллекции карт, передаваемой извне в метод списка, поэтому мы можем убедиться, что все файлы хранятся в одной и той же коллекции карт.
Настройка ListFileserVlet в файле web.xml
<Servlet> <servlet-name> listFileservlet </servlet-name> <verlet-class> me.gacl.web.controller.listfileservlet </servlet> </servlet> <servlet-mapping> <Servlet-name> ListFileservlet </Servlet-name> <Url-pattern>/servlet/listfileserverervervlet </servlet> </url-pattern>/Servletfileservelflet </servlet> </servlet-manefalle-m
Страница listfile.jsp, отображающая загруженный файл, следующая:
<%@ page language="java" import="java.util.*" pageEncoding="UTF-8"%> <%@taglib prefix="c" uri="http://java.sun.com/jsp/jstl/core" %> <!DOCTYPE HTML> <html> <head> <title>Download file display page</title> </head> <body> <!-Коллекция карты Traverse-> <C: foreach var = "me" items = "$ {filenamemap}"> <c: url value = "/servlet/downloadservlet" var = "downUrl"> <c: param = "filename" value = "$ {me.key}"> </c: param> </c: url> $ {me. href = "$ {downUrl}"> скачать </a> <br/> </c: foreach> </body> </html> Доступа к ListFileservlet, вы можете отобразить файловые ресурсы, предоставленные пользователям для загрузки на странице listfile.jsp, как показано на рисунке ниже:
3.2. Реализовать загрузку файла
Напишите сервлет для обработки загрузки файлов. Код для DownloadServlet заключается в следующем:
Пакет me.gacl.web.controller; Импорт java.io.file; импортировать java.io.fileinputstream; импортировать java.io.ioexception; импортировать java.io.outputstream; импортировать java.net.urlencoder; Импорт javax.servlet.servletexception; Импорт javax.servlet.http.httpservlet; Импорт javax.servlet.http.httpservletrequest; Импорт javax.servlet.http.httpservletresponse; Public Class DownloadServlet Extends httpservlet {public void doget (httpservletrequest -запрос, httpservletresponse response) throws servletexception, ioexception {// Получить имя файла для загрузки строкового файла = request.getparameter ("filename"); //23239283-92489-avatar.avi filename = new String (filename.getbytes ("iso8859-1"), "UTF-8"); // Загруженные файлы сохраняются в подкатарии строки/web-inf/upload string filesaverootpath = this.getServletContext (). GetRealPath ("/web-inf/upload"); // Узнайте каталог, в котором файл расположен с помощью имени файла path = findfilesavepathbyfilename (filename, filesaverootpath); // Получить файл для загруженного файла файла = новый файл (path + "//" + filename); // Если файл не существует, если (! File.exists ()) {request.setattribute («Сообщение», «Ресурс, который вы хотите загрузить, был удален !!»); request.getRequestDispatcher ("/message.jsp"). возвращаться; } // Обработка имени файла string realName = filename.substring (filename.indexof ("_")+1); // Установите заголовок ответа для управления браузером для загрузки файла response.setheader ("Content-Disposition", "Attachment; filename =" + urlencoder.encode (realName, "UTF-8")); // Читать файл для загрузки и сохранения в файл ввода FileInputStream in = new FileInputStream (path + "//" + filename); // Создание выходного потока outputStream = response.getOutputStream (); // Создать буферный байтовый буфер [] = новый байт [1024]; int len = 0; // Цикл Прочтите содержимое входного потока в буфере, в то время как ((len = in.read (buffer))> 0) {// выводить содержимое буфера в браузер, чтобы реализовать файл загрузку Out.write (Buffer, 0, Len); } // Закрыть поток ввода файла in.close (); // закрыть выходной поток out.close (); } /*** @method: findfilesavepathbyfilename* @description: Найдите путь файла, который будет загружен с помощью имени файла и корневого каталога хранилища* @anthor: 发官网* @param filenam public String findFilesavePathbyFilename (String fileName, String SaverootPath) {int hashcode = filename.hashcode (); int dir1 = hashcode & 0xf; // 0--15 int dir2 = (hashcode & 0xf0) >> 4; // 0-15 String dir = saverootpath + "//" + dir1 + "//" + dir2; // upload/2/3 upload/3/5 файл файла = новый файл (dir); if (! file.exists ()) {// Создать файл каталогов .mkdirs (); } return dir; } public void Dopost (httpservletRequest, httpservletresponse response) Throws ServletException, ioException {Doget (запрос, ответ); }}Настройка DownloadServlet в файле web.xml
<servlet> <servlet-name>DownLoadServlet</servlet-name> <servlet-class>me.gacl.web.controller.DownLoadServlet</servlet-class> </servlet> <servlet-mapping> <servlet-name>DownLoadServlet</servlet-name> <url-pattern>/servlet/DownLoadServlet</url-pattern> </servlet-mapping>
Нажмите [Загрузить] Hyperlink, отправьте запрос на DownloadServlet и обработайте его для достижения загрузки файла. Эффект работы показан на рисунке ниже:
Из выполнения результатов мы видим, что наша функция загрузки файла может нормально загружать файлы.
Приведенное выше является наиболее подробным объяснением примеров загрузки и загрузки файла, представленных редактором (рекомендуется). Я надеюсь, что это будет полезно для всех. Если у вас есть какие -либо вопросы, пожалуйста, оставьте мне сообщение, и редактор ответит всем вовремя. Большое спасибо за вашу поддержку сайту wulin.com!