I am trying to add a function to my web app which lets the users download an excel file.
I'm trying to achieve this with the following code:
#Override
public void doPost(HttpServletRequest request, HttpServletResponse response) {
File file = new File("d:/test/test.xls");
response.setContentType("application/xls");
response.addHeader("Content-Disposition", "attachment; filename=test.xls");
response.setContentLength((int) file.length());
try {
FileInputStream fileInputStream = new FileInputStream(file);
OutputStream responseOutputStream = response.getOutputStream();
int bytes;
while ((bytes = fileInputStream.read()) != -1) {
responseOutputStream.write(bytes);
}
fileInputStream.close();
responseOutputStream.close();
} catch (FileNotFoundException e) {
// TODO Auto-generated catch block
e.printStackTrace();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
I'm able to download the excel file with the above code, however the file is corrupted. If I open it with microsoft excel, I get a popup with the message:
"the file format and extension of don't match. the file could be corrupted or unsafe".
And the excel file is empty.
After running the code, the original file(d:/test/test.xls) gets also corrupted.
What am I doing wrong?
The official MIME type for Excel file .xls is application/vnd.ms-excel and for .xlsx is application/vnd.openxmlformats-officedocument.spreadsheetml.sheet.
Also, I would suggest doing response.reset() prior to writing to the output stream and responseOutputStream.flush() (important) prior to closing the response.
Try below code :
File file = null;
InputStream in = null;
OutputStream outstream = null;
try {
response.reset();
in = new FileInputStream(file);
response.setContentType("application/vnd.ms-excel");
response.addHeader("content-disposition", "attachment; filename=data.xls");
outstream = response.getOutputStream();
IOUtils.copyLarge(in, outstream);
}
catch (Exception e) {
out.write("Unable to download file");
}finally {
IOUtils.closeQuietly(outstream);
IOUtils.closeQuietly(in);
IOUtils.closeQuietly(out);
if (file != null)
file.delete();
}
dont forgot to add apache commons-io-2.4 in your dependency
Related
I am getting an image (jpeg or pdf) from a database and want to download it to the PC. However, the image is not recognised at !file.exists(). This points to File file = new File(resourceDetail.getResourseImage()); being incorrect. What is the correct way to code this please?
Note: resourceDetail.getResourseImage() is the actual image not a path.
My code is:
resourceDetail = MySQLConnection.resourceDownload(fileID);
FileInputStream stream = null;
try {
File file = new File(resourceDetail.getResourseImage());
System.out.println("resourceDetail.getResourseImage(): " + resourceDetail.getResourseImage());
if (!file.exists()) {
System.out.println("File does not exist: ");
// context.addMessage(new ErrorMessage("msg.file.notdownloaded"));
// context.setForwardName("failure");
} else {
System.out.println("File exist: ");
if (resourceDetail.getResourseImageType().equals("pdf")){
System.out.println("pdf: ");
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename='myfile.pdf'");
}else{
System.out.println("jpeg: ");
response.setContentType("image/jpeg");
response.setHeader("Content-Disposition", "attachment; filename='myfile.jpg'");
}
// response.setHeader("Content-Disposition", "attachment; filename=" + file.getName());
System.out.println("stream: ");
stream = new FileInputStream(file);
response.setContentLength(stream.available());
OutputStream os = response.getOutputStream();
os.close();
response.flushBuffer();
}
} catch (IOException e) {
e.printStackTrace();
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
resourceDetail.getResourseImage() got string data, you can directly write the data to response by using: OuputStream#write(bytes). In you case, just use ·os.write(resourceDetail.getResourseImage().getByets());` to do this.
The Sample code:
resourceDetail = MySQLConnection.resourceDownload(fileID);
try {
System.out.println(
"resourceDetail.getResourseImage(): " + resourceDetail.getResourseImage());
if (resourceDetail.getResourseImageType().equals("pdf")) {
System.out.println("pdf: ");
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename='myfile.pdf'");
} else {
System.out.println("jpeg: ");
response.setContentType("image/jpeg");
response.setHeader("Content-Disposition", "attachment; filename='myfile.jpg'");
}
response.setContentLength(resourceDetail.getResourseImage().length());
OutputStream os = response.getOutputStream();
os.write(resourceDetail.getResourseImage().getBytes());
os.close();
response.flushBuffer();
} catch (IOException e) {
e.printStackTrace();
} finally {
if (stream != null) {
try {
stream.close();
} catch (IOException e) {
e.printStackTrace();
}
}
}
While this solution does not directly answer the issue with java it does give me a solution. I started with using jQuery which worked with Chrome and not IE. I was told it was not possible to active downloading images with jQuery and that I needed to do it via java. However, I have now found:
http://danml.com/download.html
Kind regards,
Glyn
So here is the situation:
I have a .xslm file (a macro enabled excel worksheet) on server. There are no issues in opening this file on server (using ms-excel 2013).
I then edit the file using Apache POI 3.13. Save a copy of this file on server and give the other to the user for download.
(This is done just to check if we have any write issues while editing. The original purpose was just to give it as download)
The copy of this file saved on server is opened without any issues. But the one sent as download throws this error while opening it from excel 2013.
I am using Jquery.fileDownload() on the client side to make the ajax call to the server where I have my Spring Controller serving the file.
Here is my code to write the file:
Workbook workbook = null;
ServletOutputStream out = null;
InputStream inputStream = null;
FileOutputStream fos = null;
try {
OPCPackage inputFilePackage = OPCPackage.open(<original file saved on server>);
workbook = WorkbookFactory.create(inputFilePackage);
//Do Some stuff to edit workbook here
fos = new FileOutputStream("temp.xlsm");
workbook.write(fos);
fos.close();
inputStream = new FileInputStream("temp.xlsm"); // The file that is created just now
servletResponse.setContentType("application/vnd.ms-excel.sheet.macroEnabled.12");
servletResponse.setHeader("content-disposition", "attachment; filename=NewFile.xlsm");
servletResponse.setHeader("Set-Cookie", "fileDownload=true; path=/");
out = servletResponse.getOutputStream();
// workbook.write(out); // Was previously using this method to directly write to ServletOutputStream
int i;
while ((i = inputStream.read()) != -1) {
out.write(i);
}
out.flush();
// new File("temp.xlsm").delete();
}
catch (Exception e) {
LOGGER.error(e.getMessage(), e);
}
finally {
if (out != null) {
try {
out.close();
}
catch (Exception ex) {
LOGGER.error(ex.getMessage());
}
}
if (inputStream != null) {
try {
inputStream.close();
}
catch (Exception ex) {
LOGGER.error(ex.getMessage());
}
}
}
return "success";
Also I can clearly see the difference between the size of both the files.
The file which is opening without issues is (436,129 bytes) while the file throwing the error is (436,136 bytes). I am not sure from where these extra bytes are coming.
Any help would be greatly appreciated.
I want to download a file and for that I have written this code:
public void downoadResume(#PathVariable("id") int id, HttpServletResponse response) {
try {
Applicant applicant = applicantService.getOne(id);
File file = new File(DocumentConstants.DOCUMENTS_PATH + "/" + applicant.getOriginalDocPath());
// get your file as InputStream
InputStreamReader is = new InputStreamReader(new FileInputStream(file.getAbsolutePath()));
// copy it to response's OutputStream
org.apache.commons.io.IOUtils.copy(is, response.getOutputStream());
is.close();
response.flushBuffer();
} catch (IOException ex) {
ex.printStackTrace();
} catch (ResourceNotFoundException e) {
e.printStackTrace();
}
}
But I am getting this kind of response instead of file, please check:
PK!�?�*��[Content_Types].xml �(���Oo�#��H|k���i�8=��X*���8Y���3i�o��I�RLHs���罟��3��g��G�hc��e5?
�Z|�ߕE?��Q.��P\���7 ��ꀵX�OR�^?WX�?O���"��K����� �&�R�#��VC̦��QkG��3��%��P7�[�Z���Պ�T>�ʥ�9T\�݃+���1�thO�n�����dk�xP���g���&���g��pƦ���V-���3���O��a�?ġ�H���NZ�?c�˓qz�V2Y�3b��k����'��F/}(�i�ߞ`�{��wK�ۦ�]?����Z��w"���߿�r��p�<����g�x!>
��H!�9�}/=
���a�<��𬜫��#:����� ^ ���gQ'sȒGe7�x���x���h�K��G̻ޑ���9C���o٭��/��PK!���N_rels/.rels �(����JA���a�}7�
"���H�w"����w̤ھ�� �P�^����O֛���;�<�aYՠ؛`G�kxm��PY�[��g
Gΰino�/<���<�1��ⳆA$>"f3��\�ȾT�?I S?���������W����Y
ig�#��X6_�]7~
f��ˉ�ao�.b*lI�r?j)�,l0�%?�b�
6�i���D�_���, � ���|u�Z^t٢yǯ;!Y,}{�C��/h>��PK!����g�word/_rels/document.xml.rels �(����N�0��H�C�;�:`�n#�����N[��U�{{¦u۲K/��G����?���:��*4)K���H�+S��-{��c�#arQ�?�������b�� ��+��E>�q)+���?,AcƟ(�Z?m�!?E|8����`ӽ��<O�?��~�j|���Q�J�#ʥCGJp0�A�W�2a��m��s2~��OG����C��}�W������ a�z֯�n��H��?KG�?���e�cު�"�I�f�'�7,^?�����1r�'�;��*!���Fϔ�}�n,�?���?ܜ`Е��PQ,Q�?K���x߀��)�WT>)�:�88
5���;<oY
Can you please tell me what wrong I have done in this code?
You need to set the response headers and content-type which triggers the browser to treat the response content as a file and not as a web page:
response.setContentType("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
response.setHeader("Content-Disposition", "attachment; filename=download.xlsx");
It seems that you are downloading an xlsx file, Try the code below:
public void downoadResume(#PathVariable("id") int id, HttpServletResponse response) {
try {
Applicant applicant = applicantService.getOne(id);
File file = new File(DocumentConstants.DOCUMENTS_PATH + "/" + applicant.getOriginalDocPath());
response.reset();
response.resetBuffer();
response.setContentType("application/vnd.openxmlformats-officedocument.wordprocessingml.document");
response.setContentLength((int) file.length());
response.setHeader("Content-Disposition", "attachment; filename=test.xlsx");
// get your file as InputStream
InputStreamReader is = new InputStreamReader(new FileInputStream(file.getAbsolutePath()));
// copy it to response's OutputStream
org.apache.commons.io.IOUtils.copy(is, response.getOutputStream());
is.close();
response.flushBuffer();
} catch (IOException ex) {
ex.printStackTrace();
} catch (ResourceNotFoundException e) {
e.printStackTrace();
}
}
I have a web page which links to an Excel 2007 worksheet. It is a upload details in .xlsx file and download in .csv file. When I click on the download link and trying to open i get the usual dialog box to either open/save the Excel file. On clicking 'Open', I get the following warning message-
The file you are trying to open, 'filename.csv' is in a different format than specified by the file extension. Verify that the file is not corrupted and is from a trusted source before opening the file. Do you want to open the file now?
I developed this code in Java
private void downloadExcelSheet(HSSFWorkbook workbook, String sheetName){
OutputStream out = null;
try{
ByteArrayOutputStream outByteStream = new ByteArrayOutputStream();
workbook.write(outByteStream);
byte[] bytes = outByteStream.toByteArray(); //workbook.getBytes()
HttpServletResponse response = (HttpServletResponse) FacesContext.getCurrentInstance().getExternalContext().getResponse();
response.reset();
String disHeader = "Attachment;Filename=\""+sheetName+".csv\"";
response.addHeader("Content-Disposition", disHeader);
response.setContentType("text/csv");
//response.setHeader("Content-Disposition", "attachment; filename=\""+sheetName+".csv");
//response.setContentType("text/csv");
response.setContentLength(bytes.length);
out = response.getOutputStream();
out.write(bytes);
out.flush();
}catch(IOException ioe){
ioe.printStackTrace();
}
catch(Exception e){
e.printStackTrace();
}
finally{
try{
if(out!=null){
out.close();
}
}catch(IOException io){
io.printStackTrace();
}
}
}
I want to compress the dynamic created content and write to ServletOutputStream directly, without saving it as a file on the server before compressing.
For example, I created an Excel Workbook and a StringBuffer that includes strings with the SQL template. I don't want to save the dynamic content to .xlsx and .sql file on the server before zipping the files and writing to ServletOutputStream for downloading.
Sample Code:
ServletOutputStream out = response.getOutputStream();
workbook.write(byteArrayOutputStream);
zipIt(byteArrayOutputStream,out);
public static boolean zipIt(ByteArrayOutputStream input, ServletOutputStream output) {
try {
ZipOutputStream zos = new ZipOutputStream(new BufferedOutputStream(output));
ZipEntry zipEntry = new ZipEntry("test.xlsx");
zos.putNextEntry(zipEntry);
if (input != null) {
zipEntry.setSize(input.size());
zos.write(input.toByteArray());
zos.closeEntry();
}
} catch (IOException e) {
logger.error("error {}", e);
return false;
}
return true;
}
Create an HttpServlet and in the doGet() or doPost() method create a ZipOutputStream initialized with the ServletOutputStream and write directly to it:
resp.setContentType("application/zip");
// Indicate that a file is being sent back:
resp.setHeader("Content-Disposition", "attachment;filename=test.zip");
// workbook.write() closes the stream, so we first have to
// write it to a "buffer", a ByteArrayOutputStream
ByteArrayOutputStream baos = new ByteArrayOutputStream();
workbook.write(baos);
byte[] data = baos.toByteArray();
try (ZipOutputStream out = new ZipOutputStream(resp.getOutputStream())) {
// Here you can add your content to the zip
ZipEntry e = new ZipEntry("test.xlsx");
// Configure the zip entry, the properties of the file
e.setSize(data.length);
e.setTime(System.currentTimeMillis());
// etc.
out.putNextEntry(e);
// And the content of the XLSX:
out.write(data);
out.closeEntry();
// You may add other files here if you want to
out.finish();
} catch (Exception e) {
// Handle the exception
}
}