Está en la página 1de 15

Subir y Bajar Archivos en la WEB

Cmo subir archivos al servidor con


JAVA servlet?
By Rubn on August 24, 2009 10:10 PM | No Comments | No TrackBacks
Para subir archivos al servidor desde una pgina web existen diferentes alternativas en
cuanto a la tecnologa utilizada, es posible realizarlo con la mayora de tecnologas para
el servidor como por ejemplo PHP, ASP.Net y Java. Este post va a explicar como
hacerlo con la tecnologa JAVA por medio de un Servlet, en especfico con la biblioteca

com.oreilly.servlet
, adems solo se explican los elementos mnimos necesarios para hacerlo. Lo primero
que hay que conocer es lo bsico de HTML para crear un formulario que permita
seleccionar un archivo, escribir su ruta en un campo de texto y enviarlo al servidor.

El formulario (form)
Lo primero que hay que especificar con las caractersticas del formulario importantes:

action="El nombre del servlet que va a recibir el archivo"


enctype="multipart/form-data" que especifica el tipo de contenido que ser
enviado
method="POST" cuando se envan archivos no se puede usar el mtodo GET

Dentro del formulario se necesita un elemento input de tipo file y un simple botn para
activar la accin del formulario. el cdigo podra verse as:

Ahora ya con la pgina del


formulario, se requiere programar el servlet que va a recibir el archivo. Antes de
empezar se debe incluir la biblioteca com.oreilly.servlet que se descarga gratuitamente
aqu El servlet puede contener diversos mtodos y diferentes estructuras dependiendo
del tipo de proyecto, pero para este ejemplo solo se requiere el mtodo processRequest e
importar las clases necesarias de la biblioteca.

Este es un ejemplo simple, pero si se va a incluir su funcionalidad en un proyecto de


mayor complejidad se recomienda definir el funcionamiento del mtodo en una clase
que se encargue en general del manejo de archivos subidos al servidor. Espero que sea
de ayuda el contenido, cualquier duda o comentario constructivo es bienvenido.

/*
* uploadFichero.java
*
* Created on 4 de agosto de 2003, 22:26
*/
import java.io.*;
import java.net.*;
import javax.servlet.*;
import javax.servlet.http.*;
import org.apache.commons.fileupload.*;
import java.util.*;
/**
*
* @author Roberto Canales
* @version
*/
public class uploadFichero extends HttpServlet {
protected void processRequest(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.println("<html>");
out.println("<head>");
out.println("<title>Servlet</title>");
out.println("</head>");
out.println("<body>");
System.out.println("Comenzamos procesamiento ficheros");
procesaFicheros(request,out);
out.println("</body>");
out.println("</html>");
out.close();
}
void depura(String cadena)
{
System.out.println("El error es " + cadena);
}
public boolean procesaFicheros(HttpServletRequest req, PrintWriter
out ) {
try {
// construimos el objeto que es capaz de parsear la
pericin
DiskFileUpload fu = new DiskFileUpload();
// maximo numero de bytes
fu.setSizeMax(1024*512); // 512 K
depura("Ponemos el tamao mximo");
// tamao por encima del cual los ficheros son escritos
directamente en disco
fu.setSizeThreshold(4096);

// directorio en el que se escribirn los ficheros con


tamao superior al soportado en memoria
fu.setRepositoryPath("/tmp");
// ordenamos procesar los ficheros
List fileItems = fu.parseRequest(req);
if(fileItems == null)
{
depura("La lista es nula");
return false;
}
out.print("<br>El nmero de ficheros subidos es: " +
fileItems.size());
// Iteramos por cada fichero
Iterator i = fileItems.iterator();
FileItem actual = null;
depura("estamos en la iteracin");
while (i.hasNext())
{
actual = (FileItem)i.next();
String fileName = actual.getName();
out.println("<br>Nos han subido el fichero" +
fileName);
// construimos un objeto file para recuperar el
trayecto completo
File fichero = new File(fileName);
depura("El nombre del fichero es " +
fichero.getName());
// nos quedamos solo con el nombre y descartamos el
path
fichero = new
fichero.getName());

File("c:\\ficherossubidos\\" +

// escribimos el fichero colgando del nuevo path


actual.write(fichero);
}
}
catch(Exception e) {
depura("Error de Aplicacin " + e.getMessage());
return false;
}
return true;
}
/** Handles the HTTP <code>POST</code> method.
* @param request servlet request
* @param response servlet response
*/
protected void doPost(HttpServletRequest request,
HttpServletResponse response)
throws ServletException, IOException {
processRequest(request, response);

}
}

Uploading Files with Ajax


To use the XML HTTP request features in your application, you must learn to upload
files on the background with Ajax:
Define the input elements for the file upload. Use the upload() method for the
button click event to upload the file when the button is clicked.
1. <input type="file" id="uploadfile" name="uploadfile" />
<input type="button" value="upload" onclick="upload()" />

2. In the upload() method, create a FormData interface instance, and add the
file element with the attached file into it. Use the send() method to send the
FormData to the server.
3. <script>
4.
var client = new XMLHttpRequest();
5.
6.
function upload()
7.
{
8.
var file = document.getElementById("uploadfile");
9.
10.
/* Create a FormData instance */
11.
var formData = new FormData();
12.
/* Add the file */
13.
formData.append("upload", file.files[0]);
14.
15.
client.open("post", "/upload", true);
16.
client.setRequestHeader("Content-Type", "multipart/formdata");
17.
client.send(formData); /* Send to server */
18.
}
19.
20.
/* Check the response status */
21.
client.onreadystatechange = function()
22.
{
23.
if (client.readyState == 4 && client.status == 200)
24.
{
25.
alert(client.statusText);
26.
}
27.
}
</script>

Using FormData objects


The FormData object lets you compile a set of key/value pairs to send using
XMLHttpRequest. It's primarily intended for use in sending form data, but can be used
independently from forms in order to transmit keyed data. The transmitted data is in the
same format that the form's submit() method would use to send the data if the form's
encoding type were set to "multipart/form-data".

Creating a FormData object from scratch


You can build a FormData object yourself, instantiating it then appending fields to it by
calling its append() method, like this:
var formData = new FormData();
formData.append("username", "Groucho");
formData.append("accountnum", 123456);
formData.append("afile", fileInputElement.files[0]);
var xhr = new XMLHttpRequest();
xhr.open("POST", "http://foo.com/submitform.php");
xhr.send(formData);

Download File en el Servlet:


package net.codejava;
import
import
import
import

java.io.File;
java.io.FileInputStream;
java.io.IOException;
java.io.OutputStream;

import
import
import
import
import

javax.servlet.ServletContext;
javax.servlet.ServletException;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;

public class DownloadFileServlet extends HttpServlet {


protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException,
IOException {
// reads input file from an absolute path
String filePath = "E:/Test/Download/MYPIC.JPG";
File downloadFile = new File(filePath);
FileInputStream inStream = new FileInputStream(downloadFile);
// if you want to use a relative path to context root:
String relativePath = getServletContext().getRealPath("");
System.out.println("relativePath = " + relativePath);

// obtains ServletContext
ServletContext context = getServletContext();
// gets MIME type of the file
String mimeType = context.getMimeType(filePath);
if (mimeType == null) {
// set to binary type if MIME mapping not found
mimeType = "application/octet-stream";
}
System.out.println("MIME type: " + mimeType);
// modifies response
response.setContentType(mimeType);
response.setContentLength((int) downloadFile.length());
// forces download
String headerKey = "Content-Disposition";
String headerValue = String.format("attachment;
filename=\"%s\"", downloadFile.getName());
response.setHeader(headerKey, headerValue);
// obtains response's output stream
OutputStream outStream = response.getOutputStream();
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = inStream.read(buffer)) != -1) {
outStream.write(buffer, 0, bytesRead);
}
inStream.close();
outStream.close();
}
}

Configure URL mapping for this servlet in the web deployment descriptor file web.xml
as follows:
<servlet>
<description>This servlet sends file to client</description>
<display-name>DownloadFileServlet</display-name>
<servlet-name>DownloadFileServlet</servlet-name>
<servlet-class>net.codejava.DownloadFileServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>DownloadFileServlet</servlet-name>
<url-pattern>/DownloadFileServlet</url-pattern>
</servlet-mapping>

Or use the @WebServlet annotation in Servlet 3.0:


@WebServlet("/DownloadFileServlet")
public class DownloadFileServlet extends HttpServlet {
// code of the servlet...

On submission of request to upload the file, our servlet program will upload the file into
a directory in the server and then provide the URL through which user can download
the file. For security reason, user will not be provided direct URL for downloading the
file, rather they will be given a link to download the file and our servlet will process the
request and send the file to user.
We will create a dynamic web project in Eclipse and the project structure will look like
below image.

Lets look into all the components of our web application and understand the
implementation.

HTML Page for Uploading File


We can upload a file to server by sending a post request to servlet and submitting the
form. We cant use GET method for uploading file.
Another point to note is that enctype of form should be multipart/form-data.
To select a file from user file system, we need to use input element with type as file.
So we can have a simple HTML page for uploading file as:
<html>
<head></head>
<body>
<form action="UploadDownloadFileServlet" method="post"
enctype="multipart/form-data">

Select File to Upload:<input type="file" name="fileName">


<br>
<input type="submit" value="Upload">
</form>
</body>
</html>

Server File Location


We need to store file into some directory at server, we can have this directory hardcoded
in program but for better flexibility, we will keep it configurable in deployment
descriptor context params. Also we will add our upload file html page to the welcome
file list.
Our web.xml file will look like below:
<?xml version="1.0" encoding="UTF-8"?>
<web-app xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance"
xmlns="http://java.sun.com/xml/ns/javaee"
xsi:schemaLocation="http://java.sun.com/xml/ns/javaee
http://java.sun.com/xml/ns/javaee/web-app_3_0.xsd" version="3.0">
<display-name>ServletFileUploadDownloadExample</display-name>
<welcome-file-list>
<welcome-file>index.html</welcome-file>
</welcome-file-list>
<context-param>
<param-name>tempfile.dir</param-name>
<param-value>tmpfiles</param-value>
</context-param>
</web-app>

ServletContextListener implementation
Since we need to read context parameter for file location and create a File object from
it, we can write a ServletContextListener to do it when context is initialized. We can set
absolute directory location and File object as context attribute to be used by other
servlets.
Our ServletContextListener implementation code is like below.
package com.journaldev.servlet;
import java.io.File;
import
import
import
import

javax.servlet.ServletContext;
javax.servlet.ServletContextEvent;
javax.servlet.ServletContextListener;
javax.servlet.annotation.WebListener;

@WebListener
public class FileLocationContextListener implements
ServletContextListener {
public void contextInitialized(ServletContextEvent
servletContextEvent) {
String rootPath = System.getProperty("catalina.home");

ServletContext ctx = servletContextEvent.getServletContext();


String relativePath = ctx.getInitParameter("tempfile.dir");
File file = new File(rootPath + File.separator + relativePath);
if(!file.exists()) file.mkdirs();
System.out.println("File Directory created to be used for
storing files");
ctx.setAttribute("FILES_DIR_FILE", file);
ctx.setAttribute("FILES_DIR", rootPath + File.separator +
relativePath);
}
public void contextDestroyed(ServletContextEvent
servletContextEvent) {
//do cleanup if needed
}
}

File Upload Download Servlet Implementation


Update: Servlet Specs 3 added support to upload files on server in the API, so we wont
need to use any third party API. Please check out Servlet 3 Upload File.
For File upload, we will use Apache Commons FileUpload utility, for our project we
are using version 1.3, FileUpload depends on Apache Commons IO jar, so we need to
place both in the lib directory of the project, as you can see that in above image for
project structure.
We will use DiskFileItemFactory factory that provides a method to parse the
HttpServletRequest object and return list of FileItem. FileItem provides useful method
to get the file name, field name in form, size and content type details of the file that
needs to be uploaded. To write file to a directory, all we need to do it create a File
object and pass it as argument to FileItem write() method.
Since the whole purpose of the servlet is to upload file, we will override init() method to
initialize the DiskFileItemFactory object instance of the servlet. We will use this
object in the doPost() method implementation to upload file to server directory.
Once the file gets uploaded successfully, we will send response to client with URL to
download the file, since HTML links use GET method,we will append the parameter for
file name in the URL and we can utilize the same servlet doGet() method to implement
file download process.
For implementing download file servlet, first we will open the InputStream for the file
and use ServletContext.getMimeType() method to get the MIME type of the file and
set it as response content type.
We will also need to set the response content length as length of the file. To make sure
that client understand that we are sending file in response, we need to set ContentDisposition header with value as attachment; filename=fileName.
Once we are done with setting response configuration, we can read file content from
InputStream and write it to ServletOutputStream and the flush the output to client.

Our final implementation of UploadDownloadFileServlet servlet looks like below.


package com.journaldev.servlet;
import
import
import
import
import
import
import

java.io.File;
java.io.FileInputStream;
java.io.IOException;
java.io.InputStream;
java.io.PrintWriter;
java.util.Iterator;
java.util.List;

import
import
import
import
import
import
import

javax.servlet.ServletContext;
javax.servlet.ServletException;
javax.servlet.ServletOutputStream;
javax.servlet.annotation.WebServlet;
javax.servlet.http.HttpServlet;
javax.servlet.http.HttpServletRequest;
javax.servlet.http.HttpServletResponse;

import
import
import
import

org.apache.commons.fileupload.FileItem;
org.apache.commons.fileupload.FileUploadException;
org.apache.commons.fileupload.disk.DiskFileItemFactory;
org.apache.commons.fileupload.servlet.ServletFileUpload;

@WebServlet("/UploadDownloadFileServlet")
public class UploadDownloadFileServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private ServletFileUpload uploader = null;
@Override
public void init() throws ServletException{
DiskFileItemFactory fileFactory = new DiskFileItemFactory();
File filesDir = (File)
getServletContext().getAttribute("FILES_DIR_FILE");
fileFactory.setRepository(filesDir);
this.uploader = new ServletFileUpload(fileFactory);
}
protected void doGet(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
String fileName = request.getParameter("fileName");
if(fileName == null || fileName.equals("")){
throw new ServletException("File Name can't be null or
empty");
}
File file = new
File(request.getServletContext().getAttribute("FILES_DIR")+File.separa
tor+fileName);
if(!file.exists()){
throw new ServletException("File doesn't exists on
server.");
}
System.out.println("File location on
server::"+file.getAbsolutePath());
ServletContext ctx = getServletContext();
InputStream fis = new FileInputStream(file);
String mimeType = ctx.getMimeType(file.getAbsolutePath());
response.setContentType(mimeType != null?
mimeType:"application/octet-stream");
response.setContentLength((int) file.length());
response.setHeader("Content-Disposition", "attachment;

filename=\"" + fileName + "\"");


ServletOutputStream os
= response.getOutputStream();
byte[] bufferData = new byte[1024];
int read=0;
while((read = fis.read(bufferData))!= -1){
os.write(bufferData, 0, read);
}
os.flush();
os.close();
fis.close();
System.out.println("File downloaded at client successfully");
}
protected void doPost(HttpServletRequest request,
HttpServletResponse response) throws ServletException, IOException {
if(!ServletFileUpload.isMultipartContent(request)){
throw new ServletException("Content type is not
multipart/form-data");
}
response.setContentType("text/html");
PrintWriter out = response.getWriter();
out.write("<html><head></head><body>");
try {
List<FileItem> fileItemsList =
uploader.parseRequest(request);
Iterator<FileItem> fileItemsIterator =
fileItemsList.iterator();
while(fileItemsIterator.hasNext()){
FileItem fileItem = fileItemsIterator.next();
System.out.println("FieldName="+fileItem.getFieldName(
));
System.out.println("FileName="+fileItem.getName());
System.out.println("ContentType="+fileItem.getContentT
ype());
System.out.println("Size in
bytes="+fileItem.getSize());
File file = new
File(request.getServletContext().getAttribute("FILES_DIR")+File.separa
tor+fileItem.getName());
System.out.println("Absolute Path at
server="+file.getAbsolutePath());
fileItem.write(file);
out.write("File "+fileItem.getName()+ " uploaded
successfully.");
out.write("<br>");
out.write("<a
href=\"UploadDownloadFileServlet?fileName="+fileItem.getName()+"\">Dow
nload "+fileItem.getName()+"</a>");
}
} catch (FileUploadException e) {
out.write("Exception in uploading file.");
} catch (Exception e) {
out.write("Exception in uploading file.");
}
out.write("</body></html>");
}

También podría gustarte