En el desarrollo del sistema de aplicaciones web, las funciones de carga y descarga de archivos son funciones comúnmente utilizadas. Hoy, hablemos sobre la implementación de las funciones de carga y descarga de archivos en Javaweb.
Descripción general de carga de archivo
1. La función de la carga de archivos
Por ejemplo, el disco duro de la red! Se usa para cargar y descargar archivos.
Para completar un currículum completo sobre el reclutamiento de Zhilian, también debe cargar fotos.
2. Requisitos para la carga de la página
Hay muchos requisitos para cargar archivos, recuerde:
El formulario debe usarse, no un método de formulario de hipervínculo debe ser publicado, no una obtención
El enchado del formulario debe ser multipart/forma de formato
Agregue el campo Formulario de archivo en el formulario, es decir, <input type = "file" name = "xxx"/>
<Form Action = "$ {PageContext.Request.ContextPath}/FileUploadServlet" Method = "Post" Enctype = "multipart/formy-data"> username: <input type = "text" name = "username"/> <br/> file 1: <input type = "file" name = "file1"/> <BR/> file 2: <inying type "file" file "file" name = "file2"/> <br/> <input type = "subt" value = "enviar"/> </form>3. Compare la diferencia entre el formulario de carga de archivo y el formulario de texto normal
Vea la diferencia entre "Formulario de carga de archivo" y "Formulario de texto normal" a través de HTTPWatch.
El enchype del archivo de carga de archivo = "multipart/formy-data", que representa datos de formulario multiparte;
Los formularios de texto normales se pueden configurar sin configurar el atributo Enctype:
Cuando el método = "post", el valor predeterminado de Enctype es Application/X-WWW-Form-Urlencoded, lo que significa que cuando se utiliza el método = "Get", el valor predeterminado de CInPTYPE es nulo y no hay texto, por lo que no hay necesidad de probar el formulario de texto normal:
<Form Action = "$ {PageContext.Request.ContextPath}/fileUploadServlet" método = "post"> username: <input type = "text" name = "username"/> <br/> file 1: <input type = "file" name = "file1"/> <br/> file 2: <input type = "nombre" name = "file2"/<> <br/"type type1"/> <br/> file 2: <input type = "file" name = "file2"/<> <Br/"type type1"/> <Br/> archivo 2: <input type = "nombre" n. valor = "enviar"/> </form>A través de las pruebas HTTPWatch, al observar el cuerpo de datos de solicitud del formulario, descubrimos que solo hay el nombre del archivo en la solicitud, pero no hay contenido de archivo. Es decir, cuando el enctype del formulario no es multipart/formulario, la solicitud no contiene el contenido del archivo, sino solo el nombre del archivo, lo que significa que no hay diferencia entre la entrada: archivo y entrada: texto en un formulario de texto normal.
Formulario de carga de archivo de prueba:
<Form Action = "$ {PageContext.Request.ContextPath}/FileUploadServlet" Method = "Post" Enctype = "multipart/formy-data"> username: <input type = "text" name = "username"/> <br/> file 1: <input type = "file" name = "file1"/> <BR/> file 2: <inying type "file" file "file" name = "file2"/> <br/> <input type = "subt" value = "enviar"/> </form>A través de la prueba HTTPWatch, vemos la parte del cuerpo de los datos de solicitud del formulario y descubrimos que la parte del cuerpo está compuesta de múltiples componentes, cada componente corresponde a un campo de formulario, y cada componente tiene su propia información de encabezado. Debajo de la información del encabezado hay una línea en blanco, y debajo de la línea en blanco está la parte del cuerpo del campo. Múltiples partes están separadas por divisores generados aleatoriamente.
La información del encabezado del campo de texto contiene solo una información de encabezado, a saber, la disposición de contenido. El valor de esta información de encabezado tiene dos partes. La primera parte es fija, a saber, los datos de forma, y la segunda parte es el nombre del campo. Detrás de la línea en blanco está la parte principal, y la parte principal es el contenido que se completa en el cuadro de texto.
La información del encabezado del campo del archivo contiene dos encabezados, disco de contenido y tipo de contenido. Hay un nombre de archivo adicional en la Disposición de Contenido, que especifica el nombre de archivo cargado. Content-type especifica el tipo de archivo cargado. La parte principal del campo del archivo es el contenido del archivo.
Tenga en cuenta que debido a que los archivos que cargamos son todos los archivos de texto normales, es decir, archivos TXT, se pueden mostrar normalmente en httpwatch. Si los archivos cargados son exe, mp3, etc., entonces lo que ves en httpwatch está confuso.
4. Requisitos para servlets al cargar archivos
Cuando el formulario enviado es un formulario de carga de archivo, también hay requisitos para el servlet.
En primer lugar, debemos asegurarnos de que los datos del formulario de carga del archivo también se encapsulan en el objeto de solicitud.
El método request.getParameter (String) obtiene el contenido de caracteres del campo especificado, pero el formulario de carga de archivo ya no es el contenido del carácter, sino el contenido de byte, por lo que no es válido.
En este momento, puede usar el método de solicitud getInputStream () para obtener el objeto ServletInputStream. Es una subclase de InputStream. Este objeto ServletInputStream corresponde a la parte del cuerpo de todo el formulario (comenzando desde el primer divisor hasta el final), que muestra los datos en el flujo de análisis que necesitamos. Por supuesto, analizarlo es algo muy problemático, y Apache nos ha proporcionado herramientas para enviarlo: Commons-FileUplOad
Puede intentar imprimir el contenido de la transmisión request.getInputStream () y comparar los datos de solicitud en httpwatch.
Public void dopost (solicitud httpservletrequest, respuesta httpservletreponse) lanza ServletException, ioexception {inputStream in = request.getInputStream (); Cadena s = ioutils.toString (in); System.out.println (s);}------------------------- name = "Nombre de usuario" Hola ----------------------------- 7DDD3370AB2CONTENT-DISPOSITIVO: FORM-DATA; nombre = "file1"; FileName = "A.TXT" Tipo de contenido: Texto/PlainAaa ----------------------------- 7DDDD3370AB2Content-Disposition: Form-Data; nombre = "file2"; FileName = "B.txt" Tipo de contenido: Text/Plainbbb ----------------------------- 7DDD3370AB2--
bienes comunes
Por qué usar FileUpload:
Hay muchos requisitos para cargar archivos, recuerde:
Debe ser una forma de publicación;
El enchado del formulario debe ser multipart/formulario;
Agregue el campo Formulario de archivo al formulario, es decir ,.
Requisitos de servlet:
Ya no puede usar request.getParameter () para obtener datos de formulario. Puede usar request.getInputStream () para obtener todos los datos del formulario, en lugar de los datos de un elemento de formulario. Esto significa que no usa FileUpload, necesitamos analizar el contenido de request.getInputStream () nosotros mismos.
1. Descripción general de FileUpload
FileUpload es un componente de carga proporcionado por el componente Commons de Apache. Su trabajo principal es ayudarnos a analizar la solicitud. GetInputStream ()
Los paquetes JAR requeridos por el componente FileUpload son:
Commons-FileUpload.jar, paquete central
Commons-io.jar, paquete de dependencia
2. Aplicación simple de FileUpload
Las clases principales de FileUpload son: DiskFileItemFactory, ServletFileUpload, FileItem
Los pasos para usar el componente FileUpload son los siguientes:
// 1. Cree la clase de fábrica diskFileItemFactory Object DiskFileItemFactory Factory = new DiskFileItemFactory (); // 2. Cree un objeto analizador utilizando la fábrica ServletFileUpload fileUpload = new ServletFileUpload (fábrica); // 3. Use el analizador para analizar la lista de objetos de solicitud <StilEitem> list = fileUpload.Parserequest (solicitud);
DiskFileItemFactory Disk Artem Artem Factory Clase
Public DiskFileItemFactory (int SizethReshold, repositorio de archivos)
Al construir una fábrica, especifique el tamaño del búfer de memoria y la ubicación de almacenamiento de archivos temporales.
Public void setsizethreshold (int Sizethreshold)
Establezca el tamaño del búfer de memoria, predeterminado 10k
public void setRepository (repositorio de archivos)
Establezca la ubicación temporal de almacenamiento de archivos, predeterminado System.getProperty ("java.io.tmpdir").
Búfer de memoria: al cargar un archivo, el contenido del archivo cargado se guarda primero en el búfer de memoria. Cuando el tamaño de archivo cargado excede el tamaño del búfer, se generarán archivos temporales en el lado del servidor.
Ubicación temporal de almacenamiento de archivos: cargar archivos que exceden el tamaño del búfer de memoria para generar archivos temporales. Los archivos temporales se pueden eliminar a través del método delete () de FileItem
FileItem representa cada parte de los datos en el formulario de carga de archivo
Introduciremos la clase FileItem solemnemente, que es el resultado final que queremos. Un objeto FileItem corresponde a un elemento de formulario (campo de formulario). Los campos de archivo y los campos normales existen en un formulario. Puede usar el método ISFormfield () de la clase FileItem para determinar si el campo de formulario es un campo normal. Si no es un campo normal, entonces es un campo de archivo.
Nota: Debido a que el formulario de carga de archivo está codificado con datos multipart/formulario, diferentes de la codificación de URL tradicional, todos los métodos getParameter () no pueden usar setCharacterEncoding () no pueden resolver el problema confuso de los elementos de entrada.
ServletFileUPLOAD Archivo de carga Clase Class
3. Ejemplo de carga simple
Escribe un ejemplo de carga simple:
El formulario contiene un campo de nombre de usuario y un campo de archivo;
Servlet guarda archivos cargados en el directorio de carga, que muestra el nombre de usuario, el nombre del archivo, el tamaño del archivo, el tipo de archivo.
Primer paso:
Para completar index.jsp, solo se necesita un formulario. Tenga en cuenta que el formulario debe ser publicado, y el enctype debe ser mulitpart/form-data
<Form Action = "$ {PageContext.Request.ContextPath}/fileUploadServlet" método = "post" enctype = "multipart/form de forma-data"> username: <input type = "text" name = "username"/> <br/> archivo 1: <input type = "file" name = "file1"/> <BR/> <input type = "Subting" Subting " valor = "enviar"/> </form>Paso 2: Complete FileUploadServlet
Public void dopost (httpservletrequest solicitud, respuesta httpservletResponse) lanza ServletException, ioexception {// porque desea imprimir con respuesta, establecer su respuesta de codificación. // crear fábrica diskfileitemFactory dfif = new DiskFileItemFactory (); // Crear objeto analizador utilizando fábrica ServletFileUpload fileUpload = new ServletFileUpload (DFIF); Pruebe {// use el objeto Parser para analizar la solicitud y obtener la lista de FileItem List <StilEitem> list = fileUpload.Parserequest (solicitud); // Traverse todos los elementos de formulario para (fileItem fileItem: list) {// Si el elemento de formulario actual es un elemento de formulario normal si (fileItem.isformfield ()) {// Obtenga el nombre de campo del elemento de formulario actual cadena fieldame = fileItem.getFieldName (); // Si el nombre de campo del elemento de formulario actual es el nombre de usuario if (fieldName.equals ("username"))) {// imprima el contenido del elemento de formulario actual, es decir, el contenido ingresado por el elemento del formulario de username respuesta.getwriter (). Imprime ("username:" + fileitem.getstring () + "<br/>"); }} else {// Si el elemento de formulario actual no es un elemento de formulario normal, significa que el campo de archivo String name = fileItem.getName (); // Obtenga el nombre del archivo cargado // Si el nombre de archivo cargado está vacío, no se especifica ningún archivo cargado si (name == null || name.isempty () {continuar; } // Obtenga la ruta real, correspondiente a $ {directorio de proyectos}/cargas. Por supuesto, este directorio debe tener String SavePath = this.getServletContext (). GetRealPath ("/uploads"); // Crear objeto Archivo a través del archivo del directorio y el archivo de archivo Archivo de archivo = nuevo archivo (SavePath, Name); // Guardar el archivo de carga en la ubicación especificada fileitem.write (archivo); // Imprime el nombre de la respuesta del archivo de carga. // Imprima el tamaño de la respuesta del archivo de carga.getwriter (). Imprimir ("Tamaño del archivo de carga:" + fileitem.getSize () + "<br/>"); // Imprime el tipo de archivo de archivo cargado.getWriter (). Imprimir ("Tipo de archivo de carga:" + fileItem.getContentType () + "<br/>"); }}} Catch (Exception e) {Throw New ServLetException (E); }}Detalles de carga de archivo
1. Coloque el archivo cargado en el directorio web-INF
Si los archivos cargados por el usuario no se almacenan en el directorio web-INF, el usuario puede acceder directamente a los archivos cargados a través del navegador, lo cual es muy peligroso.
Si el usuario carga un archivo A.JSP y luego el usuario accede al archivo A.JSP a través del navegador, entonces se ejecutará el contenido en A.JSP. Si hay la siguiente declaración en A.JSP: RunTime.GetRuntime (). Exec ("SHUCEDOWN ST 1"); Entonces lo harás ...
Por lo general, crearemos un directorio de carga en el directorio web-INF para almacenar los archivos cargados. Para encontrar este directorio en el servlet, necesitamos usar el método GetRealPath (String) de ServletContext. Por ejemplo, existe la siguiente declaración en mi proyecto de carga1:
ServletContext ServletContext = this.getServletContext (); String SavePath = ServletContext.getRealPath ("/Web-Inf/uploads");El SavePath es: F:/Tomcat6_1/WebApps/upload1/web-inf/uploads.
2. Nombre del archivo (ruta completa, nombre del archivo)
El nombre de archivo cargado puede ser la ruta completa:
El nombre del archivo de carga obtenido por IE6 es la ruta completa, mientras que el nombre del archivo de carga obtenido por otros navegadores es solo el nombre del archivo. Todavía necesitamos lidiar con el problema de las diferencias del navegador
Name de cadena = file1fileitem.getName (); respuesta.getwriter (). Print (nombre);
Usando diferentes navegadores para probar, IE6 devolverá la ruta completa para cargar el archivo. No sé qué está haciendo IE6, lo que nos trae muchos problemas, lo que es lidiar con este problema.
También es muy simple lidiar con este problema. Ya sea una ruta completa o no, simplemente interceptamos el contenido después del último "/"
Name de cadena = file1FileItem.getName (); int LastIndex = name.lastIndexOf ("//"); // Obtenga la posición del último "/" if (lastIndex! = -1) {// Tenga en cuenta que si no es la ruta completa, entonces no habrá "/". name = name.substring (LastIndex + 1); // Obtenga el nombre del archivo} Response.getWriter (). Print (Name);3. Problema de conflicto chino
El nombre de archivo cargado contiene chino:
Cuando el nombre cargado contiene chino, debe establecer la codificación. El componente Commons-FileUpload nos proporciona dos formas de establecer la codificación:
request.setcharacterEncoding (cadena): este método es la forma más familiar de que somos.
fileupload.setheaderencdoing (cadena): este método tiene mayor prioridad que el anterior
El contenido del archivo del archivo cargado contiene chino:
Por lo general, no necesitamos preocuparnos por el contenido de cargar archivos, ¡porque guardaremos los archivos cargados en el disco duro! En otras palabras, ¿cómo se ve el archivo y cómo se ve en el servidor!
Pero si tiene tal requisito y tiene que mostrar el contenido de archivo cargado en la consola, puede usar FileItem.getString ("UTF-8") para manejar la codificación
Contenido del archivo de texto y el contenido de elemento de formulario normal use getString ("UTF-8") de la clase FileItem para manejar la codificación.
4. El problema de cargar el archivo con el mismo nombre (renombrar el archivo)
Por lo general, guardamos el archivo cargado por el usuario en el directorio de carga, pero ¿qué pasa si el usuario carga un archivo con el mismo nombre? Esto causará cobertura. El método para lidiar con este problema es usar el UUID para generar un nombre único y luego usar el "_" para conectar el nombre original cargado por el archivo.
Por ejemplo, el archivo cargado por el usuario es "mi pulgada foto.jpg". Después del procesamiento, el nombre del archivo es: "891b3881395f4175b969256a3f7b6e10_my una pulgada photo.jpg". Este método no hará que el archivo pierda su extensión. Debido a la singularidad del UUID, el archivo cargado tiene el mismo nombre, pero no habrá ningún problema con el mismo nombre en el lado del servidor.
Public void dopost (solicitud httpservletrequest, httpservletreponse respuesta) lanza ServletException, ioexception {request.setcharacterEncoding ("UTF-8"); DiskfileitemFactory dfif = new DiskFileItemFactory (); ServletFileUpload fileUpload = new ServLetFileUpload (DFIF); Pruebe {List <FileItem> list = fileUpload.parserequest (request); // Obtenga el segundo elemento de formulario, porque el primer elemento de formulario es el nombre de usuario, el segundo es el elemento de formulario de archivo fileItem fileitem = list.get (1); Name de cadena = fileitem.getName (); // Obtenga el nombre del archivo // Si el cliente está usando IE6, entonces debe obtener el nombre del archivo de la ruta completa int LastIndex = name.lastIndexof ("//"); if (lastIndex! = -1) {name = name.substring (LastIndex + 1); } // Obtenga el archivo cargado SavePath = this.getServletContext (). GetRealPath ("/web-Inf/uploads"); Cadena uuid = comunorUtils.uuid (); // generar uuid string filename = uuid + "_" + name; // El nuevo nombre de archivo es uuid + subscore + original // crea un objeto de archivo, y el archivo de archivo de archivo de archivo se guardará en la ruta especificada por este archivo // guardar, es Nombre del archivo); // Guardar el archivo item.write (archivo); } catch (Exception e) {Throw New ServLetException (e); }}5. Un directorio no puede almacenar demasiados archivos (almacenar directorio para romper)
No debe haber demasiados archivos almacenados en un directorio. En general, 1,000 archivos se almacenan en un directorio, y si hay muchos, será muy "crujido" al abrir el directorio. Puede intentar imprimir el directorio C:/Windows/System32, lo sentirá
Es decir, necesitamos poner los archivos cargados en diferentes directorios. Sin embargo, no se puede utilizar un directorio para cada archivo cargado, ya que este método conducirá a demasiados directorios. ¡Así que debemos usar algún algoritmo para "romper"!
Hay muchas maneras de romperlo, como usar fechas para romperlo, generar un directorio todos los días. También puede usar la primera letra del nombre del archivo para generar un directorio, y los archivos con la misma letra inicial se colocan en el mismo directorio.
Algoritmo de ruptura de fecha: si hay demasiados archivos cargados en un día determinado, también habrá demasiados archivos de directorio;
El algoritmo para romper la primera letra: si el nombre del archivo está en chino, porque hay demasiados chinos, conducirá a demasiados directorios.
Usamos el algoritmo hash aquí para romperlo:
Obtenga el hastio del nombre del archivo: int hcode = name.hashcode ()
Obtenga los 4 bits inferiores de Hcode, luego conviértelo en caracteres hexadecimales para obtener los 5 ~ 8 bits de Hcode, luego conviértelo en caracteres hexadecimales para generar una cadena de directorio utilizando estos dos caracteres hexadecimales. Por ejemplo, los caracteres inferiores de 4 bits son "5"
La ventaja de este algoritmo es que se genera un máximo de 16 directorios en el directorio de carga, y se genera un máximo de 16 directorios en cada directorio, es decir, 256 directorios, y todos los archivos cargados se colocan en estos 256 directorios. Si el número máximo de cada directorio es de 1000 archivos, se puede guardar un total de 256,000 archivos.
Por ejemplo, el nombre del archivo de carga es: nuevo Text Document.txt, luego obtenga el código hash de "nuevo Text Document.txt" y luego obtenga los 4 dígitos inferiores del código hash y de 5 a 8 dígitos. Si los 4 bits inferiores son: 9 y 5 ~ 8 bits son 1, entonces la ruta de guardado del archivo es una carga/9/1/
int hcode = name.hashCode (); // Obtenga el hashcode del nombre del archivo // Obtenga los 4 bits bajos de Hcode y conviértalo en la cadena Hexadecimal String dir1 = Integer.ToHexString (Hcode & 0xf); // Obtener 5 ~ 8 bits de HCode y convertirlo en la cadena Hexadecimal dir2 = INTINGER >>> 4 y 0xf); // Conecte la ruta de guardado de archivo a la ruta completa SavePath = SavePath + "/" + Dir1 + "/" + Dir2; // Porque esta ruta puede no existir, crearla como un objeto de archivo y luego crear una cadena de directorio para garantizar que el directorio ya existe nuevo antes de guardar el archivo del archivo (SavePath) .mkDirs ();
6. Límites de tamaño para archivos cargados individuales
Es muy sencillo limitar el tamaño de los archivos cargados, solo setFilesizeMax (largo) de la clase ServletFileUpload. El parámetro es el número de límite superior de bytes del archivo cargado. Por ejemplo, ServletFileUpload.SetFileSizeMax (1024*10) significa que el límite superior es de 10 kB.
Una vez que el archivo cargado excede el límite superior, se lanzará una excepción FileUploadBase.FilesInelImiteExedEdException. Podemos obtener esta excepción en el servlet y la salida "El archivo cargado excede el límite" a la página.
Public void dopost (solicitud httpservletrequest, httpservletreponse respuesta) lanza ServletException, ioexception {request.setcharacterEncoding ("UTF-8"); DiskfileitemFactory dfif = new DiskFileItemFactory (); ServletFileUpload fileUpload = new ServLetFileUpload (DFIF); // Establezca el límite superior del archivo único cargado en 10kb fileUpload.setFilesizEmax (1024 * 10); Pruebe {List <FileItem> list = fileUpload.parserequest (request); // Obtenga el segundo elemento de formulario, porque el primer elemento de formulario es el nombre de usuario, el segundo es el elemento de formulario de archivo fileitem = list.get (1); Name de cadena = fileitem.getName (); // Obtenga el nombre del archivo // Si el cliente está usando IE6, entonces debe obtener el nombre del archivo de la ruta completa int LastIndex = name.lastIndexof ("//"); if (lastIndex! = -1) {name = name.substring (LastIndex + 1); } // Obtenga el archivo cargado SavePath = this.getServletContext (). GetRealPath ("/web-Inf/uploads"); Cadena uuid = comunorUtils.uuid (); // generar uuid string fileName = uuid + "_" + name; // El nuevo nombre de archivo es uuid + subscore + nombre original int hcode = name.hashcode (); // Obtener el nombre hashcode del nombre del archivo // Obtener los 4 bits bajos de Hcode y convertirlo en HEXADECIMAL Integer.ToHexString (Hcode & 0xf); // Obtenga los 5 ~ 8 bits bajos de Hcode y conviértelo en cadena Hexadecimal String dir2 = Integer.ToHexString (Hcode >>> 4 & 0xf); // Conecte la ruta de guardado de archivo en una ruta completa SavePath = SavePath + "/" + Dir1 + "/" + Dir2; // Debido a que esta ruta no puede existir, crear un objeto de archivo y luego crear una cadena de directorio para asegurarse de que el directorio ya exista antes de guardar el archivo nuevo archivo (savePath) .mkdirs (); // Crear un objeto de archivo, y el archivo cargado se guardará en la ruta especificada por este archivo // guardarpath, es decir, el directorio de guardar archivo cargado // nombre de archivo, nombre de archivo, nombre de archivo; // Guardar fileItem.Write (archivo); } Catch (Exception e) {// Determine si el tipo de excepción arrojada es fileuploadbase.filesizeLimitExceedEdException // Si es así, significa que se excedió el límite al cargar el archivo. if (e instanciaf fileUploadbase.fileSizeLImitexExceedException) {// Guarde el mensaje de error en la solicitud Solicitar.SetAttribute ("msg", "¡Carga fallida! ¡El archivo cargado excedió 10kb!"); // reenviar a la página index.jsp! En la página index.jsp, debe usar $ {msg} para mostrar la solicitud del mensaje de error.getRequestDispatcher ("/index.jsp"). ADELAR (Solicitar, respuesta); devolver; } tirar nueva ServletException (e); }}7. Límite de tamaño total para cargar archivos
El formulario para cargar un archivo puede permitir que se carguen varios archivos, por ejemplo:
A veces necesitamos limitar el tamaño de una solicitud. ¡Es decir, el número máximo de bytes para esta solicitud (suma de todos los elementos de formulario)! Implementar esta función también es muy simple. Solo necesita llamar al método SetSizEmax (Long) de la clase ServLetFileUpload.
Por ejemplo, FileUpload.SetSizEmax (1024 * 10);, el límite superior para toda la solicitud es de 10 kB. Cuando el tamaño de la solicitud excede los 10 kb, el método Parserequest () de la clase ServletFileUpload lanzará una excepción de archivo de Uploadbase.sizeLimitexExitExExitExExitExExiteException.
8. Tamaño de caché y directorio temporal
Piénselo, si subo una película de Blu-ray, guarde la película primero en la memoria y luego la copia en el disco duro del servidor a través de la memoria, ¿se puede comer su memoria?
Por lo tanto, el componente FileUpload no puede guardar todos los archivos en la memoria. FileUpload determinará si el tamaño del archivo excede los 10 kb. Si es así, guarde el archivo en el disco duro. Si no lo excede, guárdelo en la memoria.
10kb es el valor predeterminado de FileUpload, podemos configurarlo.
Cuando el archivo se guarda en el disco duro, FileUpload guarda el archivo en el directorio temporal del sistema. Por supuesto, también puede establecer el directorio temporal
Public void dopost (solicitud httpservletrequest, httpservletreponse respuesta) lanza ServletException, ioexception {request.setcharacterEncoding ("UTF-8"); DiskfileitemFactory dfif = new DiskFileItemFactory (1024*20, nuevo archivo ("f: // temp")); ServletFileUpload fileUpload = new ServLetFileUpload (DFIF); Pruebe {List <FileItem> list = fileUpload.parserequest (request); FileItem fileItem = list.get (1); Name de cadena = fileitem.getName (); String SavePath = this.getServletContext (). GetRealPath ("/web-Inf/uploads"); // Guardar fileItem.Write (Path (Path (SavePath, Name));} Catch (Exception E) {Throw New ServLetException (e);}} private Archivo Path (String SavePath, String FileName) {// Obtenga el nombre de archivo int de la ruta completa LastIndex = FileName.LastIndexOf ("//"); if (LastIndex! = -1) FileName.Substring (LastIndex + 1); Dir2 ;/Descarga de archivos
1. Descargar 1 a través de Servlet
Los recursos descargados deben colocarse en el directorio web-INF (está bien mientras el usuario no pueda acceder directamente a través del navegador) y luego descargarlo a través del servlet.
Proporcione el hipervínculo en la página JSP, enlace a DownloadServlet y proporcione el nombre del archivo para descargar. Luego, DownloadServlet obtiene la ruta real del archivo y escribe el archivo en la transmisión Response.getOutputStream ().
descargar.jsp
<Body> Esta es mi página JSP. <br> <a href = "<c: url value = '/downloadServlet? path = a.avi' ///>"> a.avi </a> <br/> <a href = "<c: url value = '/downloadServlet? valor = '/descargarservlet? path = a.txt' /////> "> a.txt </a> <br/> </body>
DownloadServlet.java
public void doget (HTTPServletRequest Solicitud, respuesta httpservletResponse) lanza ServLetException, ioException {string filename = request.getParameter ("ruta"); String filePath = this.getServletContext (). GetRealPath ("/Web-Inf/uploads/" + FileName); Archivo archivo = nuevo archivo (filepath); if (! file.exists ()) {Response.getWriter (). imprime ("El archivo que desea descargar no existe!"); devolver; } Ioutils.copy (nuevo FileInputStream (archivo), respuesta.getOutputStream ());}El código anterior tiene los siguientes problemas:
1. Puede descargar A.Avi, pero el nombre del archivo en el cuadro de descarga es descargaServlet;
2. No puede descargar A.JPG y A.TXT, pero mostrarlos en la página.
2. Descargar 2 a través de Servlet
Vamos a tratar el problema en el ejemplo anterior, para que el nombre de archivo correcto se pueda mostrar en el cuadro de descarga, y los archivos A.JPG y A.TXT se pueden descargar
Maneje el problema anterior agregando el encabezado de discusión de contenido. Cuando se establece el encabezado de discusión de contenido, el navegador aparecerá en el cuadro de descarga
¡Y también puede especificar el nombre del archivo descargado a través del encabezado de discosión de contenido!
Cadena filename = request.getParameter ("ruta"); String filePath = this.getServletContext (). GetRealPath ("/Web-Inf/uploads/" + FileName); Archivo archivo = nuevo archivo (filepath); if (! file.exists ()) {Response.getWriter (). imprime ("El archivo que desea descargar no existe!"); devolver; } Respuesta.AddHeader ("Disposición de contenido", "Adjunto; FileName =" + FileName); Ioutils.copy (nuevo FileInputStream (archivo), respuesta.getOutputStream ());Aunque el código anterior ya puede manejar la descarga de archivos como TXT y JPG, y también manejar el problema de mostrar los nombres de los archivos en el cuadro de descarga, si el nombre del archivo descargado está en chino, entonces aún no puede
3. Descargar 3 a través de Servlet
¡A continuación se muestra el problema de manejar la visualización de chino en el cuadro de descarga!
De hecho, esta pregunta es muy simple. ¡Solo necesitas codificar chino a través de la URL!
descargar.jsp
<a href = "<c: url value = '/downloadServlet? Path = Este asesino no es demasiado frío.avi' ///>"> Este asesino no es demasiado frío.avi </a> <br/> <a href = "<c: url value = '/downloadservlet? href = "<c: url value = '/downloadServlet? Path = Descripción.txt'/>"> Descripción.txt </a> <br/>
DownloadServlet.java
String filename = request.getParameter ("ruta"); // En la solicitud GET, el parámetro chino contiene el chino y debe convertirse usted mismo. // Por supuesto, si usa el "Filtro de codificación global", entonces no necesita tratarlo aquí FileName = new String (FileName.getBytes ("ISO-8859-1"), "UTF-8"); String filePath = this.getServletContext (). Archivo (FilePath); if (! File.Exists ()) {Response.getWriter (). PRIT ("El archivo que desea descargar no existe!"); return;} // Todos los navegadores utilizarán la codificación local, es decir, el sistema operativo chino usa gbk // después de que el navegador reciba este nombre de archivo, usará ISO-8859-1 para fileName = new String (fileName.getBytes nombre de archivo); ioutils.copy (nuevo FileInputStream (archivo), respuesta.getOutputStream ());Lo anterior es todo el contenido de este artículo. Espero que sea útil para el aprendizaje de todos y espero que todos apoyen más a Wulin.com.