Pregunta

Estoy escribiendo una aplicación sencilla que permite al usuario cargar imágenes.Después de la carga, el usuario puede etiquetarlos o eliminarlos.

Descubrí cómo cargar los archivos y guardarlos una vez cargados.Estoy siguiendo una ruta global donde se guardan las imágenes.En la base de datos guardo los metadatos sobre las imágenes como nombre de archivo, etiquetas, etc.

Estoy usando Java/JSP (específicamente el marco Stripes pero mi problema es genérico).

Mi pregunta es ¿dónde guardo estos archivos de imágenes una vez cargados?

Ahora tengo dos aplicaciones web implementadas en un servidor Tomcat.Una aplicación web principal y otra es donde subo las imágenes.

Pero esto no funciona porque no puedo ver las imágenes cargadas en la aplicación principal hasta que vuelva a implementar/reiniciar Tomcat.

Parece que Tomcat no selecciona automáticamente las imágenes recién cargadas.

¿Alguien tiene alguna solución?

Este es un proyecto simple, por lo que no quiero almacenarlos en una base de datos ni usar Apache para las imágenes.Todo eso es demasiado complicado para este pequeño proyecto.

Gracias.

¿Fue útil?

Solución

Sin duda, no almacenar las imágenes en la base de datos, pero tendrá que almacenar la ruta de la imagen en la base de datos. Esto le permitirá almacenar la imagen en cualquier lugar.

Desde que está utilizando dos aplicaciones Tomcat, la mejor opción puede ser la de almacenar las imágenes fuera de cualquiera de aplicación y transmitir la imagen de nuevo al usuario en lugar de dejar que Tomcat gestionar los archivos. De lo contrario, me gustaría preguntar por qué usted está tratando de hacer esto con dos aplicaciones web.

Otros consejos

Sin embargo, almacenar imágenes cargadas dentro del directorio de la aplicación web no es una buena idea, y usted lo sabe.

Por cierto, quizás quieras mirar esto. hilo de desbordamiento de pila, últimamente discutió dónde almacenar las imágenes.Puede que no resuelva tu problema, pero seguramente te dará más confianza en lo que estás haciendo.

He resuelto esto de diferentes maneras.

En primer lugar, la forma no portátil, es que Glassfish (y yo creo Tomcat también) le permite asignar un directorio externo a la jerarquía aplicaciones web. Esto funciona muy bien y hace exactamente lo que quiere. Se le permite almacenar sus imágenes en un directorio externo lejos de su aplicación web, sin embargo, todavía sirven para arriba.

Sin embargo, esta técnica no es portátil.

La manera de que lo he hecho de forma portátil es mediante la creación de un filtro.

Se coloca el filtro de un lugar obvio, por ejemplo "/ images".

Lo que hace el filtro es la siguiente:

  • comprueba la imagen (o cualquier cosa, funciona con cualquier recurso estático) en un directorio especial dentro de la aplicación web. Para nuestro ejemplo usaremos la URL "/ webapp / imágenes".

  • Si no existe el archivo, se copia el archivo desde su ubicación externa al lugar apropiado dentro de la aplicación web. Por lo tanto, digamos que la url es reqyest "/images/banner.gif". Y que sus archivos se almacenan en el disco en "/ home / app / imágenes". Por lo tanto, nuestro fichero fuente es "/home/app/images/banner.gif". a continuación, lo copiamos a donde queremos que en el árbol de aplicación web. Utilizamos "ServletContext.getRealPath" para esto. Por lo tanto, el destino será "ServletContext.get realpath (" / webapp / images / banner.gif "). Sólo tienes que copiar el origen al destino.

  • Si ya existe el archivo, o existe ahora, sólo tiene interés la imagen real en /webapp/images/banner.gif.

eficazmente al final tener un caché de archivos dentro de su árbol de implantación aplicaciones web. El lado negativo es que es una memoria caché, por lo que hay que mantener (es decir, se debe comprobar si el original es más reciente que la memoria caché, asegúrese de borrar si se elimina la fuente, etc.). Además, duplica sus recursos, por lo que sus imágenes se consumen, con el tiempo, el doble de espacio en disco. Por último, está el costo inicial de copia en el arranque.

Sin embargo, funciona, y que le impide tener que servir a los recursos estáticos utilizando su propio código. (¿Qué es la tercera solución, asignar un filtro / servlet para interceptar las direcciones URL y simplemente transmitir su auto.)

Me gustaría ver el constructo dentro de Tomcat (suponiendo que exista) para hacer el mapeo para usted. Sé que existe en Glassfish. (Google alternatedocroot de Glassfish para ver cómo funciona.)

Yo estaba usando dos aplicaciones web para evitar la sobre escritura de las imágenes subidas en caso de que REDEPLOY un nuevo archivo principal de la guerra aplicación.

Sin embargo, como usted menciona no hay otra opción, pero para transmitir a través de un servlet o algo supongo que puedo mantenerlos fuera del directorio Tomcat.

quería evitar escribir este Transmisión de servlet. Demasiado pequeño proyecto para hacer frente a todo el lío (como tipo de contenido adecuado, 404, etc.) al escribir el servlet de streaming.

import java.io.BufferedInputStream;
import java.io.BufferedOutputStream;
import java.io.File;
import java.io.FileInputStream;
import java.io.IOException;
import java.io.PrintWriter;

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

/**
 * Image streaming Servlet.
 */
public class ImageDisplayServlet extends HttpServlet {
    private static final long serialVersionUID = 1L;

    /**
     * @see HttpServlet#HttpServlet()
     */
    public ImageDisplayServlet() {
        super();
    }

    /**
     * @see HttpServlet#doGet(HttpServletRequest request, HttpServletResponse response)
     */
    protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        String relativePath = trimToEmpty(request.getPathInfo());

        // Make sure no one try to screw with us. 
        // This is important as user can literally access any file if we are not careful
        if(isXSSAttack(relativePath) == false) {
            String pathToFile = this.getServletContext().getRealPath(request.getPathInfo());
            File file = new File(pathToFile);

            System.out.println("Looking for file " + file.getAbsolutePath());

            // show a 404 page
            if(!file.exists() || !file.isFile()) {
                httpError(404, response);
            } else {
                try {
                    streamImageFile(file, response);
                } catch(Exception e) {
                    // Tell the user there was some internal server error.\
                    // 500 - Internal server error.
                    httpError(500, response);
                    e.printStackTrace();
                }
            }
        } else {
            // what to do if i think it is a XSS attack ?!?
        }
    }

    private void streamImageFile(File file, HttpServletResponse response) {
        // find the right MIME type and set it as content type
        response.setContentType(getContentType(file));
        BufferedInputStream bis = null;
        BufferedOutputStream bos = null;
        try {
            response.setContentLength((int) file.length());

            // Use Buffered Stream for reading/writing.
            bis = new BufferedInputStream(new FileInputStream(file));
            bos = new BufferedOutputStream(response.getOutputStream());

            byte[] buff = new byte[(int) file.length()];
            int bytesRead;

            // Simple read/write loop.
            while (-1 != (bytesRead = bis.read(buff, 0, buff.length))) {
                bos.write(buff, 0, bytesRead);
            }
        } catch (Exception e) {

            throw new RuntimeException(e);
        } finally {
            if (bis != null) {
                try {
                    bis.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    // To late to do anything about it now, we may have already sent some data to user.
                }
            }
            if (bos != null) {
                try {
                    bos.close();
                } catch (IOException e) {
                    e.printStackTrace();
                    // To late to do anything about it now, we may have already sent some data to user.
                }
            }
        } 
    }

    private String getContentType(File file) {
        if(file.getName().length() > 0) {
            String[] parts = file.getName().split("\\.");
            if(parts.length > 0) {
                // only last part interests me
                String extention = parts[parts.length - 1];
                if(extention.equalsIgnoreCase("jpg")) {
                    return "image/jpg";
                } else if(extention.equalsIgnoreCase("gif")) {
                    return "image/gif"; 
                } else if(extention.equalsIgnoreCase("png")) {
                    return "image/png";
                }
            }
        }
        throw new RuntimeException("Can not find content type for the file " +  file.getAbsolutePath());
    }

    private String trimToEmpty(String pathInfo) {
        if(pathInfo == null) {
            return "";
        } else {
            return pathInfo.trim();
        }
    }

    private void httpError(int statusCode, HttpServletResponse response) {
        try {
            response.setStatus(statusCode);
            response.setContentType("text/html");
            PrintWriter writer = response.getWriter();
            writer.append("<html><body><h1>Error Code: " + statusCode + "</h1><body></html>");
            writer.flush();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    private boolean isXSSAttack(String path) {
        boolean xss = false;
        // Split on the bases of know file separator
        String[] parts = path.split("/|\\\\");

        // Now verify that no part contains anything harmful
        for(String part : parts) {
            // No double dots .. 
            // No colons :
            // No semicolons ;
            if(part.trim().contains("..") || part.trim().contains(":") || part.trim().contains(";")) {
                // Fire in the hole!
                xss = true;
                break;
            }
        }
        return xss;
    }

    /**
     * @see HttpServlet#doPost(Ht/promotions/some.jpgtpServletRequest request, HttpServletResponse response)
     */
    protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
        doGet(request, response);
    }
}

La autorización aquí es un servlet que rápidamente escribí que puede transmitir imágenes:

Aquí está la lista de limitaciones y sabe cuestiones:

  • pueden tener un uso vulnerabilidad XSS con cuidado
  • No es la producción de su uso inmediato como referencia
  • Imágenes necesitan en el directorio de la aplicación web. Se puede cambiar fácilmente, pero me da pereza (no vale la pena que el proyecto es demasiado pequeño)
  • Sólo jpg corriente, GIF o PNG archivos.

Uso:

Digamos que implementa esta aplicación web llamados imágenes como una aplicación independiente.

http://www.example.com/images/promotions/promo.jpg

significa que debe haber un directorio en "promociones" con imagen "promo.jpg" con imágenes en esta aplicación web.

PS: No pregunte por qué estoy haciendo esto sólo contenedor servlet solución que aspira a lo grande

.
  <servlet>
    <description></description>
    <display-name>ImageDisplayServlet</display-name>
    <servlet-name>ImageDisplayServlet</servlet-name>
    <servlet-class>com.example.images.ImageDisplayServlet</servlet-class>
  </servlet>
  <servlet-mapping>
    <servlet-name>ImageDisplayServlet</servlet-name>
    <url-pattern>/*</url-pattern>
  </servlet-mapping>

Ah ya configurar su servlet como la de arriba para obtener los mejores resultados: P

Licenciado bajo: CC-BY-SA con atribución
No afiliado a StackOverflow
scroll top