Implementação de Download e Exibição de Imagens no Navegador

Para controlar como os navegadores tratam recursos como imagens ou arquivos, é essencial configurar os cabeçalhos HTTP corretamente na resposta do servidor. Isto permite forçar o download de arquivos que normalmente seriam exibidos, como imagens, ou exibir imagens dinamicamente a partir de fluxos de dados.

Download de Arquivos no Navegador

Para induzir o navegador a baixar um arquivo em vez de exibi-lo, defina os seguintes cabeçalhos na resposta:

  • Content-Type: application/octet-stream para indicar dados binários genéricos.
  • Content-Disposition: attachment; filename="nomeDoArquivo.ext" para tratar o conteúdo como um anexo.
  • Content-Length: tamanhoEmBytes para informar o tamanho do arquivo.

Em seguida, envie o conteúdo do arquivo como um fluxo de bytes. Exemplo em Java usando Servlet:

public void enviarArquivoParaDownload(String caminhoArquivo, HttpServletRequest req, HttpServletResponse resp) throws IOException {
    File arquivo = new File(caminhoArquivo);
    try (InputStream entrada = new BufferedInputStream(new FileInputStream(arquivo));
         OutputStream saida = new BufferedOutputStream(resp.getOutputStream())) {
        
        resp.setContentType("application/octet-stream");
        resp.setHeader("Content-Disposition", "attachment; nomeArquivo=\"" + URLEncoder.encode(arquivo.getName(), "UTF-8") + "\"");
        resp.setContentLengthLong(arquivo.length());
        
        byte[] buffer = new byte[8192];
        int bytesLidos;
        while ((bytesLidos = entrada.read(buffer)) != -1) {
            saida.write(buffer, 0, bytesLidos);
        }
    }
}

No framework Restlet, a abordagem é semelhante, encapsulando a lógica de escrita em uma representação de saída:

public Representation baixarArquivo(byte[] dadosArquivo, String nomeArquivo) {
    Representation output = new OutputRepresentation(MediaType.APPLICATION_OCTET_STREAM) {
        @Override
        public void write(OutputStream os) throws IOException {
            os.write(dadosArquivo);
            os.flush();
        }
    };
    Disposition disp = new Disposition(Disposition.TYPE_ATTACHMENT);
    disp.setFilename(nomeArquivo);
    output.setDisposition(disp);
    return output;
}

Exibição de Imagens a Partir de Fluxos

Para que o navegador renderize uma imagem diretamente, como em uma tag <img>, configure o cabeçalho Content-Type com o tipo MIME correto (ex: image/jpeg para JPEG) e forneça o conteúdo como um fluxo. O cabeçalho Content-Disposition não é necessário para exibição direta.

Exemplo de implementação com Servlet:

public void exibirImagem(String caminhoImagem, HttpServletResponse resp) throws IOException {
    File imagem = new File(caminhoImagem);
    try (InputStream entrada = new BufferedInputStream(new FileInputStream(imagem));
         OutputStream saida = new BufferedOutputStream(resp.getOutputStream())) {
        
        resp.setContentType("image/jpeg");
        resp.setContentLengthLong(imagem.length());
        
        byte[] buffer = new byte[4096];
        int bytesLidos;
        while ((bytesLidos = entrada.read(buffer)) != -1) {
            saida.write(buffer, 0, bytesLidos);
        }
    }
}

No Restlet, crie uma representação com o tipo de mídia apropriado:

public Representation exibirImagem(byte[] dadosImagem) {
    return new OutputRepresentation(MediaType.IMAGE_JPEG) {
        @Override
        public void write(OutputStream os) throws IOException {
            os.write(dadosImagem);
            os.flush();
        }
    };
}

Ao definir esses cabeçalhos e enviar os dados binários, o navegador interpreta corretamente se deve baixar o arquivo ou renderizar a imagem inline.

Tags: Java Servlet Restlet Framework HTTP Headers Image Streaming Browser Download

Publicado em 6-25 21:00