File Download via Spring does not work in Firefox - java

I have written a program to upload and download files (.doc, .xls and .txt) from DB (mySQL). It is written using Spring MVC. The upload and download is working correctly in IE however in Firefox it is not working as excepted.
To download the file a link is provided in the JSP on click of which the "File Download" dialog box will pop-up. In IE this dialog box pops up and allows to open and/or save the file in the correct format (i.e. .doc, .xls and/or .txt).
In Firefox it is doing the following on click on the link :
For .doc files, it opens the files (no File Download pop-up)
For .xls files, the File Download pop-up is seen however the file extension is not taken as .xls instead taking it as file.do
FileController Class
public class FileController extends AbstractFormController{
SearchResultService searchResultService;
public void setSearchResultService(SearchResultService searchResultService){
this.searchResultService = searchResultService;
}
#Override
protected ModelAndView handleRequestInternal(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception {
ResultSet result = searchResultService.getAttachment(Integer.parseInt(arg0.getParameter("prbId")));
byte[] buff = new byte[100000];
try {
result.next();
if(!(result.getBinaryStream(1)==null)){
String filename = "fname."+result.getString("file_ext");
if(result.getString("file_ext").equals("txt")){
InputStream is = result.getBinaryStream(1);
OutputStream out = arg1.getOutputStream();
arg1.reset();
int bytesRead;
while ((bytesRead = is.read(buff)) != -1) {
out.write(buff, 0, bytesRead);
}
arg1.setContentType("");
arg1.setHeader("content-disposition", "attachment; filename="+filename);
is.close();
out.flush();
out.close();
}else{
arg1.reset();
if(result.getString("file_ext").equals("doc")||result.getString("file_ext").equals("docx")){
arg1.setContentType("application/msword");
}else if(result.getString("file_ext").equals("xls")||result.getString("file_ext").equals("xlsx")){
arg1.setContentType("application/vnd.ms-excel");
}else if(result.getString("file_ext").equals("pdf")){
arg1.setContentType("application/pdf");
}
arg1.setHeader("Content-Desposition","attachment; filename="+filename);
byte[] bytesGot = result.getBytes(1);
ServletOutputStream outs = arg1.getOutputStream();
outs.write(bytesGot);
outs.flush();
outs.close();
}
}
} catch (SQLException e) {
e.printStackTrace();
}
return new ModelAndView();
}
}
JSP that calls FileController class
Download File
All the extensions are saved/retrieved in the db correctly. Please help.

For point 2 - You have a spelling mistake in setting the header.
arg1.setHeader("Content-Desposition","attachment; filename="+filename);
It should be Content-Disposition not Content-Desposition.
For point 1 - try resetting your browser preferences. See this link for more information.

You need to set proper headers. I am setting these headers to download my .xls file and its working.
response.setHeader("Pragma", "public");
response.setHeader("Expires", "0");
response.setHeader("Cache-Control", "must-revalidate, post-check=0, pre-check=0");
response.setHeader("Content-type", "application-download");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
response.setHeader("Content-Transfer-Encoding", "binary");

public class FileController extends AbstractFormController{
SearchResultService searchResultService;
public void setSearchResultService(SearchResultService searchResultService){
this.searchResultService = searchResultService;
}
#Override
protected ModelAndView handleRequestInternal(HttpServletRequest arg0, HttpServletResponse arg1) throws Exception {
ResultSet result = searchResultService.getAttachment(Integer.parseInt(arg0.getParameter("prbId")));
byte[] buff = new byte[100000];
try {
result.next();
if(!(result.getBinaryStream(1)==null)){
String filename = "fname."+result.getString("file_ext");
if(result.getString("file_ext").equals("txt")){
InputStream is = result.getBinaryStream(1);
OutputStream out = arg1.getOutputStream();
arg1.reset();
int bytesRead;
while ((bytesRead = is.read(buff)) != -1) {
out.write(buff, 0, bytesRead);
}
response.setContentType("text/plain");
arg1.setHeader("content-disposition", "attachment; filename="+filename);
is.close();
out.flush();
out.close();
}else{
arg1.reset();
if(result.getString("file_ext").equals("doc")||result.getString("file_ext").equals("docx")){
arg1.setContentType("application/msword");
}else if(result.getString("file_ext").equals("xls")||result.getString("file_ext").equals("xlsx")){
arg1.setContentType("application/msexcel");
}else if(result.getString("file_ext").equals("pdf")){
arg1.setContentType("application/pdf");
}
arg1.setHeader("Content-Disposition","attachment; filename="+filename);
byte[] bytesGot = result.getBytes(1);
ServletOutputStream outs = arg1.getOutputStream();
outs.write(bytesGot);
outs.flush();
outs.close();
}
}
} catch (SQLException e) {
e.printStackTrace();
}
return new ModelAndView();
}
}

Related

Downloading multiple pdf files using Spring Boot RestController

I am trying to use a Spring Boot RestController to download multiple pdf files.But for some reason only the first file is downloaded.The program does not throw any error.Not sure what the issue is.Is Multipart needed for this?
#RequestMapping(value = "downloadAgain", method = RequestMethod.GET)
#ResponseBody
public void newRun(HttpServletResponse response) {
String fileName1="pdf1.pdf";
String fullName1="C://Users//pdf1.pdf";
newDownloadRun(response,fileName1,fullName1);
String fileName2="pdf2.pdf";
String fullName2="C://Users//pdf2.pdf";
newDownloadRun(response,fileName2,fullName2);
}
public void newDownloadRun(HttpServletResponse response,String fileName,String fullName) {
response.setContentType("application/pdf");
response.setHeader( "Content-Disposition", "attachment;filename="+ fileName );
response.setHeader("Content-disposition", "attachment; filename=" + fileName);
try {
BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
FileInputStream fis = new FileInputStream(fullName);
int len;
byte[] buf = new byte[1024];
while((len=fis.read(buf))> 0) {
bos.write(buf,0,len);
}
bos.close();
response.flushBuffer();
}catch(Exception ex) {
ex.printStackTrace();
}
}
Http protocol designed to send one file per request. if you want to send multiple files you need to prepare it as multipart/related. Look into this article https://www.motobit.com/tips/detpg_multiple-files-one-request/

PDF is rendered as text content when trying to view pdf file in my browser

I have an error when I want to download or see in the web browser a pdf file, somehow the file is generated in text. Has anyone had this problem?
Is my code:
public void downloadPDF(File ArchivoPDF, String NombrePDF) throws IOException{
FacesContext facesContext = FacesContext.getCurrentInstance();
ExternalContext externalContext = facesContext.getExternalContext();
HttpServletResponse response = (HttpServletResponse) externalContext.getResponse();
BufferedInputStream input = null;
BufferedOutputStream output = null;
try{
input = new BufferedInputStream(new FileInputStream(ArchivoPDF),DEFAULT_BUFFER_SIZE);
response.reset();
response.setHeader("Content-Type","application/pdf");
response.setHeader("Content-Length",String.valueOf(ArchivoPDF.length()));
response.setHeader("Content-Disposition","attachment; filename=\"" + NombrePDF + ".pdf\"");
output = new BufferedOutputStream(response.getOutputStream(),DEFAULT_BUFFER_SIZE);
byte[] buffer = new byte[DEFAULT_BUFFER_SIZE];
int length;
while((length = input.read(buffer)) > 0){
output.write(buffer,0,length);
}
output.flush();
} finally{
close(output);
close(input);
}
facesContext.responseComplete();
}
private static void close(Closeable resource){
if(resource != null){
try{
resource.close();
} catch(IOException e){
e.printStackTrace();
}
}
}
and my component commandButton is:
<a4j:commandButton id="btnGenerarAllPDF" style="width:130px;"
rendered="#{clsGestionReclamoRealSrv.objComponente.blVerBtnGenerarExpedienteElectronico}"
value="Generar Expediente"
onclick="#{rich:component('modCargando')}.show();"
action="#{clsGestionReclamoRealSrv.doGenerarAllPDF}"
oncomplete="#{rich:component('modCargando')}.hide();"
reRender="frmRegistrarReclamo"/>
and call method in:
File ArchivoPDF = new File(pathFolderArch + String.valueOf(this.getObjReclamo().getNuIdReclamo()) + ".pdf");
if(ArchivoPDF.isFile()){
ClsUtils.deleteCarpeta(pathFolderTemp);
downloadPDF(ArchivoPDF,String.valueOf(this.getObjReclamo().getNuIdReclamo()));
} else {
logger.error("Error al generar el PDF.");
}
and the result is text in browser.
Text replace pdf
They know how to fix it.
I believe the appropriate way to set the content type is something like,
response.setContentType("Content-Type","application/pdf");
This could download your file as pdf as expected. To view the file in browser try something like,
response.setHeader("Content-Disposition", "inline; filename=\"" + NombrePDF + ".pdf\";");

Create and Download Excel from Web Explorer with Java in Spring MVC

I want to create an Excel file from a method in Java and download it in a browser.
I have found an example on this post where you create the Excel file, but I want to create the .xls file and download it from a web browser.
How can I do that?
I finally found a solution for my problem...!!
This is working for me:
#RequestMapping("/downloadFile")
public void downloadFile(HttpServletRequest request, HttpServletResponse response) {
try {
String fileName = "C:/excelFile.xls";
HSSFWorkbook workbook = new HSSFWorkbook();
HSSFSheet sheet = workbook.createSheet("firstSheet");
HSSFRow rowhead = sheet.createRow((short) 0);
rowhead.createCell(0).setCellValue("No.");
rowhead.createCell(1).setCellValue("Name");
rowhead.createCell(2).setCellValue("Address");
rowhead.createCell(3).setCellValue("Email");
HSSFRow row = sheet.createRow((short) 1);
row.createCell(0).setCellValue("1");
row.createCell(1).setCellValue("Carlos");
row.createCell(2).setCellValue("Costa Rica");
row.createCell(3).setCellValue("myNameh#gmail.com");
FileOutputStream fileOut = new FileOutputStream(fileName);
workbook.write(fileOut);
fileOut.close();
System.out.println("Your excel file has been generated!");
//Code to download
File fileToDownload = new File(fileName);
InputStream in = new FileInputStream(fileToDownload);
// Gets MIME type of the file
String mimeType = new MimetypesFileTypeMap().getContentType(fileName);
if (mimeType == null) {
// Set to binary type if MIME mapping not found
mimeType = "application/octet-stream";
}
System.out.println("MIME type: " + mimeType);
// Modifies response
response.setContentType(mimeType);
response.setContentLength((int) fileToDownload.length());
// Forces download
String headerKey = "Content-Disposition";
String headerValue = String.format("attachment; filename=\"%s\"", fileToDownload.getName());
response.setHeader(headerKey, headerValue);
// obtains response's output stream
OutputStream outStream = response.getOutputStream();
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = in.read(buffer)) != -1) {
outStream.write(buffer, 0, bytesRead);
}
in.close();
outStream.close();
System.out.println("File downloaded at client successfully");
} catch (Exception ex) {
System.out.println(ex);
}
}
If you want to trigger a Java process from a Web Browser (HTTP request), then you need an application server (like Tomcat) to accept your HTTP request and execute some server-side code (Servlet). A main method like in the example cannot be launched by a HTTP request. Look here if you never wrote a Servlet before.
This has nothing to do with Excel, but this post shows how to download a file from a Spring MVC controler.
#RequestMapping(value = "/files/{file_name}", method = RequestMethod.GET)
public void getFile(#PathVariable("file_name") String fileName, HttpServletResponse response) {
try {
// get your file as InputStream
InputStream is = ...;
// copy it to response's OutputStream
org.apache.commons.io.IOUtils.copy(is, response.getOutputStream());
response.flushBuffer();
} catch (IOException ex) {
log.info("Error writing file to output stream. Filename was '{}'", fileName, ex);
throw new RuntimeException("IOError writing file to output stream");
}
}

Error downloading file in Android default browser, java.io.IOException: Write failure

I have .apk file in my resources dir and I want to download it directly from Mobile devices.
All is fine when using Chrome, or when I try it in my PC, but when using default Android Browser I get a .htm file and a:
ClientAbortException: java.io.IOException: Write failure
I dont understand what is happens or if it´s a browser´s bug.
Exception thrown after some loops in:
out.write(outputByte, 0, 4096);
Any suggestions? Thanks!
This is my code:
#RequestMapping(method = RequestMethod.POST)
public String download(#ModelAttribute("apkDownload") #Valid ApkDownloadDTO apkDownload, ModelMap model, HttpServletRequest request,
HttpServletResponse response, BindingResult result) {
InputStream is = ApkDownloadController.class.getResourceAsStream("/apk/mine.apk");
try {
response.addHeader("Content-Description", "File Transfer");
response.addHeader("Content-Type", " application/vnd.android.package-archive");
response.addHeader("Content-Disposition", "attachment; filename=mine.apk");
response.addHeader("Content-Transfer-Encoding", "binary");
ServletOutputStream out = response.getOutputStream();
byte[] outputByte = new byte[4096];
while (is.read(outputByte, 0, 4096) != -1) {
out.write(outputByte, 0, 4096);
}
is.close();
out.flush();
out.close();
} catch (IOException e) {
log.error(e);
} finally {
try {
is.close();
} catch (IOException e) {
log.error(e);
}
}
return null;
}
Try Using some other browser other then default browser,
e.g UC Browser, Chrome, etc
You'll get to known then if its default browser problem or not

Save file dialog not appearing

I am tryig to make a song available for download on my website. I am using a download servlet that I have used before to make zip files available for download. I have run through the code and everything appears to be working, the output stream reads the entire file but the save dialog box does not appear. Any ideas? Thanks for your help. Code is as follows:
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String song = request.getParameter("song");
StringBuilder filePath = new StringBuilder();
try {
Thread.sleep(1);
String[] info = getSongInfo(song);
filePath.append("D:\\My Music\\My Song.m4a");
File file = new File(filePath.toString());
if (!file.exists()) {
throw new FileNotFoundException(file.getAbsolutePath());
}
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Type", "audio/mp4a-latm");
response.setHeader("Content-disposition", "attachment; filename="+song+".m4a");
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
byte[] buf = new byte[4096];
while (true) {
int length = bis.read(buf);
if (length == -1) {
break;
}
bos.write(buf, 0, length);
}
bos.flush();
bos.close();
bis.close();
} catch (InterruptedException e) {
System.err.println("Error message: " + e.getMessage());
}
}
Called using:
dojo.xhrGet(
{
url: "/downloadSong?song="+item.title[0]
});
You cannot download files by ajax. JavaScript has due to security reasons no facility to spawn a Save As dialogue nor to store them in disk. It will consume the response, but it can't do anything sensible with it.
You need to use window.location instead:
window.location = "/downloadSong?song=" + item.title[0];
Thanks to the Content-Disposition: attachment header, it won't affect the currently opened page.

Categories

Resources