Server:
#RequestMapping(value = "/url/{size}/{id}", method = RequestMethod.GET)
public void getPortfolioFile(HttpServletResponse response,
#PathVariable("id") int id,
#PathVariable("size") int size)
{
File img = provider.getImage(id, size);
if (img != null) {
try {
FileCopyUtils.copy(FileCopyUtils.copyToByteArray(img), response.getOutputStream());
String mimeType = img.toURL().openConnection().getContentType();
response.setContentType(mimeType);
response.setContentLength((int) img.length());
response.setHeader("Content-Transfer-Encoding", "binary");
response.setHeader("Content-Type", "binary/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=\"" + img.getName() + "\"");
} catch (IOException e) {
e.printStackTrace(System.err);
}
}
}
html:
<img src="/url/2/${id}" onerror="$('#c').empty();" />
the problem is that IE10 don't display image. response body contains image, headers is 200 OK. whan can it be?
check in:
Chrome v43.0.2357.132
FireFox Developer Edition v40
IE v10
You need to set the headers before you write the content, else they are ignored.
String mimeType = img.toURL().openConnection().getContentType();
response.setContentType(mimeType);
response.setContentLength((int) img.length());
response.setHeader("Content-Transfer-Encoding", "binary");
response.setHeader("Content-Type", "binary/octet-stream");
response.setHeader("Content-Disposition", "attachment;
FileCopyUtils.copy(FileCopyUtils.copyToByteArray(img), response.getOutputStream());
EDIT:
you content-type "binary/octet-stream" does not make sense.
Here I would expect a "image/gif" or other appropriate content type.
I also would eliminate the content-disposition header.
Related
I used this method to download and get content type
#GetMapping("/downloadFile/")
public ResponseEntity<Resource> downloadFile(#RequestParam String fileName, HttpServletRequest request) {
// Load file as Resource
Resource resource = fileStorageService.loadOneFileAsResource(fileName);
// Try to determine file's content type
String contentType = null;
try {
contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
} catch (IOException ex) {
logger.info("Could not determine file type.");
}
// Fallback to the default content type if type could not be determined
if(contentType == null) {
contentType = "application/octet-stream";
}
return ResponseEntity.ok()
.contentType(MediaType.parseMediaType(contentType))
.header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
.body(resource);
}
But always detect my content "application/octet-stream", what is problem and what should I do?
thanks in advance.
You can download the file, save it and then use the following:
Path path = Paths.get(resource.getURI());
String contentType = Files.probeContentType(path);
This should give you the content type. Look over here.
I am getting a resulting file but in the response I am getting gibberish symbols
here is the code I am trying
public ResponseEntity<InputStreamResource> getExcel(String filePath) throws Exception {
try {
Path excelPath = Paths.get(filePath);
byte[] excel = Files.readAllBytes(excelPath);
ByteArrayInputStream excelToByte = new ByteArrayInputStream(excel);
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
headers.add("Content-Disposition", "attachment; filename=ABCGeneratedExcel.xls");
return ResponseEntity
.ok()
.headers(headers)
.contentType(MediaType.APPLICATION_OCTET_STREAM)
.body(new InputStreamResource(excelToByte));
}
catch (NoSuchFileException e) {
System.out.prinln("does not exist");
}
You should use HttpServletResponse instead. And let Spring framework initialize it by declaring as Controller method's parameter. Because you will write the excel file as binary stream, do not define the return type.
Then write the response stream after setting the contentType and header for excel downloading.
public void getExcel(String filePath, HttpServletResponse response) {
byte[] excel = Files.readAllBytes(excelPath);
String fileName = "anyFileName.xlsx"
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment;filename=" + fileName);
response.getWriter().write(excel); // in fact, you need to surround this by try-catch block
}
Path filePath = pathToFolder.resolve(fileName).normalize();
Resource resource = new UrlResource(filePath.toUri());
if (resource.exists()) {
return resource;
} else {
throw new NotFoundException(String.format("File %s not found", fileName));
}
Where path to File - in your directory, and file name - name of file in your directory.
Next step is:
Resource resource = service.downloadFile(fileName);
String contentType = null;
try {
contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
} catch (IOException e) {
log.info("Could not determine file type");
}
if (contentType == null) {
contentType = MediaType.APPLICATION_OCTET_STREAM_VALUE;
}
return ResponseEntity
.ok()
.contentType(MediaType.parseMediaType(contentType))
.header(HttpHeaders.CONTENT_DISPOSITION, String.format(
"%s; filename=%s", content.name().toLowerCase(), resource.getFilename()
)
)
.body(resource);
Where first %s - attachment - for downloading, and inline - for rendering file in the browser.
Second %s - name of file (note that if you are storing your file in the file system, use file name with extension).
#GetMapping(value = "/draftReport", produces=MediaType.APPLICATION_JSON_UTF8_VALUE)
public void generateDraftResport(#RequestParam("schoolID") String schoolID, HttpServletResponse response) {
HttpHeaders headers = new HttpHeaders();
headers.setContentType(MediaType.APPLICATION_OCTET_STREAM);
response.setHeader("Content-Disposition", "attachment; filename=" + "draft_export.xlsx");
try {
InputStream is = exportHandler.draftReport(schoolID);
org.apache.commons.io.IOUtils.copy(is, response.getOutputStream());
response.flushBuffer();
System.out.println("Successfully written");
}
catch (IOException ex) {
log.info("Error writing file to output stream. " + ex);
System.out.println("Error while writing file");
}
}
The draftReport method returns an InputStream containing the XSSFWorkbook data. On invoking my Api '/draftReport', I want that file to be available to the browser to save. What am I missing, if at all? I get all the success logs, but no download popup.
My Controller to which the request is mapped-
I return the value from AJAX, to the controller-
$.ajax({
type: 'GET',
dataType: 'json',
contentType:"application/json",
url:"/Putty/downloadProcess/?param="+param
});
#RequestMapping(value = "/downloadProcess", method = RequestMethod.GET)
protected void download(#RequestParam("param") String value, HttpServletResponse response)
throws ServletException, IOException {
Properties prop = new Properties();
InputStream input = new FileInputStream("config.properties");;
prop.load(input);
System.out.println(value);
String path = prop.getProperty("path.MS1");
String filepath= path.concat(value);
System.out.println(filepath);
File downloadFile = new File(filepath);
FileInputStream inStream = new FileInputStream(downloadFile);
String mimeType = "application/octet-stream";
System.out.println("MIME type: " + mimeType);
// modifies response
response.setContentType(mimeType);
response.setContentLength((int) downloadFile.length());
// forces download
String headerKey = "Content-Disposition";
String headerValue = String.format("attachment; filename=\"%s\"", downloadFile);
response.setHeader(headerKey, headerValue);
System.out.println(response);
// obtains response's output stream
OutputStream outStream = response.getOutputStream();
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = inStream.read(buffer)) != -1) {
outStream.write(buffer, 0, bytesRead);
}
inStream.close();
outStream.close();
This displays the filenames on my JSP
<c:forEach var="listValue" items="${files}">
<label onClick="download('${listValue}')">${listValue}</label>
<br>
</c:forEach>
The problem is that, I can see the MIME type on my console, along with the value returned by AJAX- The filename. But I do not get the Download dialog box, when I click on the file names, displayed on my JSP. Am I not handling the requests properly or I am missing something else.
Thanks!
Try it
ServletOutputStream out = response.getOutputStream();
response.setContentType("application/octet-stream");
if (file.isFile())
{
response.setHeader("Content-Disposition", "attachment;filename=\"" + downloadFile.getName() + "\"");
try (FileInputStream inputStream = new FileInputStream(downloadFile ))
{
IOUtils.copy(inputStream, out);
}
}
The Open/Save dialogue appears by default so we can not force anything. It is a browser specific settings that you cant change on the client side.
For Mozilla Firefox example :
I´m trying to open a pdf that I have created using iText library in my browser, but it fails.
This is the code I´m using to send to browser
File file = new File(path);
try{
//InputStream stream=blob.getBinaryStream();
InputStream streamEntrada = new FileInputStream(file);
//ServletOutputStream fileOutputStream = response.getOutputStream();
PrintWriter print = response.getWriter();
int ibit = 256;
while ((ibit) >= 0)
{
ibit = streamEntrada.read();
print.write(ibit);
}
response.setContentType("application/text");
response.setHeader("Content-Disposition", "attachment;filename="+name);
response.setHeader("Pragma", "cache");
response.setHeader("Cache-control", "private, max-age=0");
streamEntrada.close();
print.close();
return null;
}
catch(Exception e){
return null;
}
}
I tried with FileOutputStream but isn´t works. I´m desperate.
Thank you.
Now, I´m trying this way, but it doesn´t work:
public class MovilInfoAction extends DownloadAction{
protected StreamInfo getStreamInfo(ActionMapping mapping, ActionForm form, HttpServletRequest request, HttpServletResponse response) throws Exception {
//Here the creation of the PDF
//Storing data
PdfData dPdf = pdf.drawPDF(terminal);
String path = dPdf.getPath();//Path
String name = dPdf.getName()+".pdf";//Pdf´s name
String contentType = "application/pdf";//ContentType
response.setContentType(contentType);
response.setHeader("Content-Disposition","attachment; filename="+name);
response.setHeader("Cache-control", "private, max-age=0");
response.setHeader("Content-Disposition", "inline");
File file = new File(path);
byte[] pdfBytes = es.vodafone.framework.utils.Utils.getBytesFromFile(file);
return new ByteArrayStreamInfo(contentType, pdfBytes);
}
protected class ByteArrayStreamInfo implements StreamInfo {
protected String contentType;
protected byte[] bytes;
public ByteArrayStreamInfo(String contentType, byte[] bytes) {
this.contentType = contentType;
this.bytes = bytes;
}
public String getContentType() {
return contentType;
}
public InputStream getInputStream() throws IOException {
return new ByteArrayInputStream(bytes);
}
}
}
You specify the mimetype as application/text, when it should be application/pdf.
You should set the Header and ContentType before you write the data.
And set the Content Type to application/pdf.
change
response.setContentType("application/text");
to
response.setContentType("application/pdf");
and if you want your pdf to open in browser then make following change
response.setHeader("Content-Disposition", "inline");
Put the filename in double quote "
response.setHeader("Content-Disposition","attachment; filename=\"" + attachmentName + "\"");
Android Default Browser requires GET Request. It does not understand POST Request and hence cannot download the attachment. You can send a GET request as by sending GET request, it resolved my problem. Android browser generates a GET request on its own and sends it back to server. The response received after second request will be considered final by the browser even if GET request is sent on first time by the servlet.