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-streampara indicar dados binários genéricos.Content-Disposition: attachment; filename="nomeDoArquivo.ext"para tratar o conteúdo como um anexo.Content-Length: tamanhoEmBytespara 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.