Pergunta

Eu estou escrevendo um aplicativo simples que permite que imagens de um usuário de upload. Após o upload, o usuário pode marcá-los ou removê-los.

Eu descobri como fazer o upload dos arquivos e guardá-las uma vez que os arquivos são carregados. Eu estou mantendo o acompanhamento de um caminho global onde as imagens são mantidas. No banco de dados I manter os metadados sobre as imagens como nome do arquivo, etiquetas, etc.

Eu estou usando Java / JSP (especificamente Stripes quadro, mas o meu problema é genérico).

A minha pergunta é onde posso manter esses arquivos de imagem, uma vez que são carregadas?

Agora eu tenho dois aplicativos web implantados em um servidor Tomcat. Uma aplicação web principal e outro é o que eu fazer o upload das imagens.

Mas isso não funciona como eu não pode ver as imagens carregadas no aplicativo principal até que eu redeploy / restart Tomcat.

Parece que Tomcat não pegar as imagens recém-enviados automaticamente.

Alguém tem alguma solução?

Este é um projeto simples, então eu não quero armazená-los em um banco de dados ou usar o Apache para imagens. Isso é tudo muito complicado para este pequeno projeto.

Graças.

Foi útil?

Solução

Definitivamente não armazenar as imagens no banco de dados, mas você vai querer guardar o caminho da imagem no banco de dados. Isso permitirá que você para armazenar a imagem em qualquer lugar.

Uma vez que você estiver usando dois aplicativos Tomcat, sua melhor aposta pode ser para armazenar as imagens fora de qualquer aplicativo e transmitir as costas para o usuário em vez de deixar tomcat gerenciar os arquivos. Caso contrário, gostaria de perguntar por que você está tentando fazer isso com duas aplicações web.

Outras dicas

No entanto, o armazenamento de imagens carregadas dentro do diretório web-app não é uma coisa sensata a fazer, e você sabe disso.

A propósito, você pode querer olhar este stackoverflow enrosque , recentemente discutido onde armazenar as imagens. Pode não resolver o problema, certamente irá lhe dar mais confiança no que você está fazendo.

Eu já resolveu isso de maneiras diferentes.

Em primeiro lugar, a forma não-portáteis, é que Glassfish (e eu acredito Tomcat também) permite mapear um diretório externo para a hierarquia webapps. Isso funciona muito bem e faz exatamente o que você quer. Ele permite que você armazenar suas imagens em um diretório externo longe do seu webapp, mas ainda servir-los.

No entanto, esta técnica não é portátil.

A maneira de eu fiz isso portably é através da criação de um filtro.

Você coloca a algum lugar filtro óbvio, diga "/ images".

O que o filtro faz é esta:

  • verifica a imagem (ou qualquer coisa, ele funciona com qualquer recurso estático) em um diretório especial dentro do webapp. Para o nosso exemplo vamos usar a url "/ webapp / imagens".

  • Se o arquivo não existir, nós copiar o arquivo do seu local externo para o local apropriado dentro do webapp. Então, vamos dizer que o url reqyest é "/images/banner.gif". E que seus arquivos são armazenados no disco em "/ home / app / imagens". Então, o nosso arquivo de origem é "/home/app/images/banner.gif". Em seguida, copie-o para onde quer que ele na árvore webapp. Usamos "ServletContext.getRealPath" para isso. Assim, o destino será "ServletContext.get realpath (" / webapp / images / banner.gif ") copiar. Apenas a fonte para o destino.

  • Se o arquivo já existia ou existe agora, simplesmente para a frente para a imagem real em /webapp/images/banner.gif.

Efetivamente você acaba tendo um cache de arquivos dentro de seus webapps árvores implantação. O lado ruim é que é um cache, por isso precisa ser mantido (ou seja, você deve verificar se o original é mais recente do que o seu cache, certifique-se de excluir se a fonte for excluído, etc.). Além disso, ele duplica os seus recursos, para que suas imagens irão consumir, finalmente, duas vezes mais espaço em disco. Finalmente, há o custo inicial de cópia no arranque.

No entanto, ela não funciona, e que o impede de ter que servir recursos estáticos usando seu próprio código. (Que é o 3º solução, mapear um filtro / servlet para interceptar os URLs e simplesmente transmiti-lo a si próprio.)

Eu olhava para a construção dentro de Tomcat (assumindo que ela existe) para fazer o mapeamento para você. Eu sei que existe no Glassfish. (Google alternatedocroot para Glassfish para ver como ele funciona.)

Eu estava usando duas aplicações da Internet para evitar o excesso de escrever as imagens carregadas no caso de eu reimplementar um novo arquivo de guerra aplicativo principal.

Mas como você menciona não há outra opção, mas para transmitir-lhes através de um Servlet ou algo que eu acho que pode mantê-los fora tomcat diretório.

Eu queria evitar escrever este Servlet Streaming. Apenas demasiado pequeno projeto para lidar com toda a confusão (como tipo de conteúdo apropriado, 404, etc.) ao escrever o 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);
    }
}

Ok Aqui está um servlet que eu rapidamente escreveu que pode transmitir imagens:

Aqui está a lista de limitações e saber questões:

  • Pode ter uso vulnerabilidade de XSS com cuidado
  • Não produção de pronto uso como referência
  • Imagens precisa no diretório do aplicativo web. Pode ser facilmente mudar, mas eu muito preguiçoso (não vale a pena o projeto é muito pequeno)
  • Apenas fluxo jpg, gif ou png arquivos.

Uso:

Vamos dizer que você implantar esse aplicativo Web chamado imagens como aplicativo separado.

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

significa que deve haver um diretório no "promoções" com "imagem promo.jpg" com nesta aplicação imagens web.

PS:. Não pergunte por que estou fazendo isso só solução Servlet Container que suga grande momento

  <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>

Oh ya configurar o Servlet como acima para obter melhores resultados: P

Licenciado em: CC-BY-SA com atribuição
Não afiliado a StackOverflow
scroll top