miércoles, 11 de febrero de 2009

Como hacer la descarga de ficheros con servlets

Pues este es un problema muy curioso, como sabéis los servlet devuelven un stream como respuesta. La configuración más usada para los servlet es que la respuesta sea de tipo html, que especificamos:

response.setContentType("text/html");

Pero el contenido de la respuesta lo podemos cambiar a cualquier otro Mime type:

http://www.webmaster-toolkit.com/mime-types.shtml

Según esto podemos hacer que nuestro servlet devuelva cualquier tipo de fichero.

En el siguiente ejemplo escribo un servlet capaz de enviarnos un fichero zip de cualquier parte del disco del servidor. (Nota. esto hay que manejarlo con cuidado porque puede producir un hueco de seguridad gordisimo)

package org.company.servlet.readfile;


import javax.servlet.*;
import javax.servlet.http.*;
import java.io.*;
import java.util.*;
import java.net.*;


/**
*

This class handles Streaming Data Content


**/
public class Readfile extends HttpServlet {

    public void init(ServletConfig config) throws ServletException {
        super.init(config);
    }

    /*
    * This Method Handles Post
    *
    * @param HttpServletRequest request
    * @param HttpServletResponse response
    */
    public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }

    /*
    * This Method Handles Get
    *
    * @param HttpServletRequest request
    * @param HttpServletResponse response
    */
    public void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String urlstr = null;
        UserBean user = (UserBean)         request.getSession().getAttribute("user");
        try {
            response.reset();
            urlstr = request.getParameter("filename");
            ServletOutputStream sOutStream = response.getOutputStream();
            streamBinaryData(user.getName(),             urlstr, sOutStream, response);


        } catch (Exception e) {
            e.printStackTrace();
        }
    }


    private void streamBinaryData(String username, String file, ServletOutputStream outstr, HttpServletResponse resp) throws IOException{
        String ErrorStr = null;

        try {
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        String inFile = "/midirectorio/" + file;
        int tam = (int) new File(inFile).length();
        bis = new BufferedInputStream(new FileInputStream(inFile));

        try {
            //Asignamos el tipo de fichero zip
            resp.setContentType("application/x-zip-compressed"); //Cualquier mime type
            //Seteamos el tamaño de la respuesta
            resp.setContentLength(tam);
            resp.setHeader("Content-Disposition", "attachment;filename=\"" + file + "\"");

            bos = new BufferedOutputStream(outstr);

            // Bucle para leer de un fichero y escribir en el otro.
            byte[] array = new byte[1000];
            int leidos = bis.read(array);
            while (leidos > 0) {
                bos.write(array, 0, leidos);
                leidos = bis.read(array);
            }


            } catch (Exception e) {
                e.printStackTrace();
                ErrorStr = "Error Streaming the Data";
                outstr.print(ErrorStr);
            } finally {
                if (bis != null) {
                    bis.close();
                }
                if (bos != null) {
                    bos.close();
                }
                if (outstr != null) {
                    outstr.flush();
                    outstr.close();
                }
            }

            } catch (Exception e) {
                System.out.println("Fichero no encontrado");
                resp.sendRedirect("fileNotFound.jsp");

            }

        }
    }

Con este servlet conseguimos que en el navegador aparezca la típica ventanita de "descargas" al hacer una llamada al servlet, que recibe como parámetro el nombre del fichero. Este es el motivo por el que debemos tener cuidado al usar esto ya que podríamos crear un hueco de seguridad y que el usuario final se pueda descargar cualquier fichero de nuestro servidor.

Lo mejor sería tener un directorio controlado del que sacar los ficheros como en el ejemplo, o que se filtre el filename de entrada para saber que está entre los permitidos, etc ...

Configurar la red manualmente en Ubuntu

Hace tiempo que no escribo en el blog, el motivo es que ando muy muy liado con el trabajo y no me ha dejado tiempo para escribir los artículos que tenía en mente. Pero hoy me ha pasado que al instalarme una máquina nueva con la ultima versión de ubuntu. Si uso la configuración gráfica de red, está no se porqué no se guarda, sólo está activa mientras esté el ordenador encendido pero al reiniciarlo toda la configuración se pierde.

Bueno pues este artículo intenta explicar como configurarla manualmente para que se quede permanente ya que desde el UI no lo he conseguido.

1 Paso:

> vi /etc/network/interfaces

El contenido debemos editarlo para que quede:

auto lo
iface lo inet loopback

iface eth0 inet static
address XXX.XXX.X.XXX
netmask 255.255.255.XXX
gateway XXX.XXX.X.XXX
nameserver XXX.XXX.X.XXX
domain midominio.es

auto eth0


Esta configuración especifica:
address -> dirección ip
netmask -> máscara de red
gateway -> la puerta de enlace, suele ser la dirección ip del rooter
nameserver -> (opcional) dirección ip del servidor de dns, puedes poner tantos como servidores dns tengas
domain -> para configurar el dominio de red en el que te encuentras


Nota. Esta configuración está hecha para una conexión cableada por eso usa eth0

Paso 2:

Aunque en este fichero podemos especificar los dns, lo suyo es especificarlos en el fichero

> vi /etc/resolv.conf

El contenido del fichero debería ser:

nameserver XXX.XXX.X.XXX

Nota. Tantos nameserver como servidores de dns tengamos.

Bueno pues con esto, tu configuración quedará permanetemente configurada, de hecho
si el NetworkManager (UI para la configuración de red de ubuntu) funcionara bien, en estos ficheros debe poner algo así como

# Generated by NetworkManager

Eso es todo.