Error while file download - java

in my servlet, I am passing a file path using cookies and downloading a file as below
protected void doGet(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
// TODO Auto-generated method stub
String b = null;
Cookie[] cookies = request.getCookies();
if (cookies != null) {
for (Cookie cookie : cookies) {
if (cookie.getName().equals("thecookie")) {
b = cookie.getValue();
}
}
}
BufferedReader br = new BufferedReader(new FileReader(b+"/logs.txt"));
String path = br.readLine();
br.close();
File file = new File(path+"/Results.xlsx");
FileInputStream fileIn = new FileInputStream(file);
ServletOutputStream out = response.getOutputStream();
byte[] outputByte = new byte[4096];
//copy binary contect to output stream
while(fileIn.read(outputByte, 0, 4096) != -1)
{
out.write(outputByte, 0, 4096);
}
fileIn.close();
out.flush();
out.close();
}
Everything works fine and the file is getting downloaded but, I want to download Results.xlsx and the file that is being downloaded is download.zip and this download.zip is same size as my Results.xlsx file but is not getting opened by excel.
How do I do this right??

You're writing the data to the output stream, but you're not setting a content type or a filename. You should use:
response.setHeader("Content-Disposition", "attachment; filename=Result.xslx");
response.setContentType(
"application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
(Before you start writing to the output stream.)
Additionally, your stream-copying loop is broken - you're always writing out 4096 bytes even if you haven't read that much. It should be:
int bytesRead;
while((bytesRead = fileIn.read(outputByte)) != -1)
{
out.write(outputByte, 0, byteRead);
}
... and you should use a try-with-resources or finally block to make sure you close your stream even if there's an exception.
(Or use a utility method from a library such as Guava.)

Related

Java download file from server cannot identify file type

Below is the controller for downloading files. The files can be multiple types, such as PDF, excel and doc. The issue is that the file type downloaded is always "File" instead of .pdf, .excel or .doc. I have to manually choose a application to open the file. Does anyone know what is wrong?
#RequestMapping(value="/download/system-of-record", method = RequestMethod.GET)
public void systemOfRecordDownload(HttpServletRequest request, HttpServletResponse response, HttpSession session) throws IOException {
int formId = Integer.parseInt(request.getParameter("id"));
Form form = formService.findFormByPrimaryKey(formId);
String formName = form.getName();
String formPath = form.getInternalLink();
response.reset();
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment; filename=\"" + formName + "\"");
try {
File f = new File(formPath);
OutputStream os = response.getOutputStream();
byte[] buf = new byte[8192];
FileInputStream is = new FileInputStream(f);
int readByte = 0;
while ((readByte = is.read(buf, 0, buf.length)) > 0) {
os.write(buf, 0, readByte);
os.flush();
}
os.close();
is.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
}
Thats because you have set the mime type to octet-stream
Either use Files.probeContentType(path) to get the correct mime type of the file object and replace it in place of octet-stream
Or use your own logic to specify a mime type there from this list

Error : IllegalStateException in Java. Cannot forward after response has been committed

Help needed,
I am working for to download the file in Java Servlet and after the file download can't send the request to page.
File is downloaded successfully and getting the illegalStateException when I try forward the request to the page.
here is the code
public void fileDownload(String stringFileToDownload, HttpServletResponse response) throws Exception{
FileInputStream inStream = null;
OutputStream outStream = null;
try{
File downloadFile = new File(stringFileToDownload); //Reads input file
inStream = new FileInputStream(downloadFile);
response.setContentType("application/zip-compressed"); //MIME type of the file
response.setContentLength((int) downloadFile.length());
response.setHeader("Content-Disposition", "attachment; filename=Time.zip");
//response's output stream
outStream = response.getOutputStream();
byte[] buffer = new byte[4096];
int bytesRead = -1;
while ((bytesRead = inStream.read(buffer)) != -1) {
outStream.write(buffer, 0, bytesRead);
}
}
catch(Exception ex){
throw ex;
}
finally{
//response.flushBuffer();
try{
if(inStream != null){
inStream.close();
}
if(outStream != null){
//outStream.flush();
outStream.close();
}
}
catch(Exception ex){
throw ex;
}
}
}
I called this method from servlet; redirecting from the servlet to the another page
Calling code:
FileDownloadFromWeb fileDownloadFromWeb = new FileDownloadFromWeb();
fileDownloadFromWeb.fileDownload(stringarchiveFile, response); //Allow to download
Request Dispatcher objRequestDispatcher = request.getRequestDispatcher(objProperties.getProperty("SUCC‌​ESS_DOWNLOAD"));
objRequestDispatcher.forward(request, response);
Here when you write to output stream response will be committed ( outStream.write(buffer, 0, bytesRead); ) and then if you try to use request.forward() it will defiantly throw error.
solution to this problem is to set your file content as object in request parameter and than use it in jsp or use redirect rather than forward
probably your problem can be fixed by taking separate servlet for file download refer this after download a image ,i want to redirect on another page, but not able to

Java request getInputStream return empty stream

I've got a problem with getInputStream from doPost request and setting filename before. It's giving me a file with right filename but empty file 0kB. If I'll comment setting fileName than I'll get not empty file.
My process: From android apps I'm archiving PDF file to upload server like http POST. At server doPost is like below method.
How to set filename and get not empty file?
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
String fileName = null;
//Get all the parts from request and write it to the file on server
//getFileName return filename
for (Part part : request.getParts()) {
fileName = getFileName(part);
}
File saveFile = new File(SAVE_DIR + fileName);
// opens input stream of the request for reading data
InputStream inputStream = request.getInputStream();
// opens an output stream for writing file
FileOutputStream outputStream = new FileOutputStream(saveFile);
byte[] buffer = new byte[BUFFER_SIZE];
int bytesRead = -1;
while ((bytesRead = inputStream.read(buffer)) != -1) {
outputStream.write(buffer, 0, bytesRead);
}
outputStream.close();
inputStream.close();
// sends response to client
response.getWriter().print("UPLOAD DONE");
}
Edit:
private String getFileName(Part part) {
String contentDisp = part.getHeader("content-disposition");
System.out.println("content-disposition header= " + contentDisp);
String[] tokens = contentDisp.split(";");
for (String token : tokens) {
if (token.trim().startsWith("filename")) {
return token.substring(token.indexOf("=") + 2, token.length() - 1);
}
}
return "";
}
Solution:
//Get the right Part
final Part filePart = request.getPart("uploadedfile");
//Writes file to location
filePart.write(filePart.getSubmittedFileName());
Part offers a getInputStream() method, so you should use that instead of request.getInputStream(); when you're dealing with parts.
However...
Part.write() is a convenience method to write this uploaded item to disk, so you can just use part.write(SAVE_DIR + part.getSubmittedFileName()); and it's all handled for you (note that getSubmittedFileName() is available only for Servlet 3.1).
Do outputstream.flush() before doing outputstream.close()

How to read a server file and output that as a downloadable file in users web browser in XPages

I need to read a file (that is not available on web) on the server and output it to the user as a downloadable file.
The scenario is
The user click a link from an XPage
The request is sent to the server which reads a predefined file in the server file system
The file is brought back to the user as a downloadable file in the webbrowser.
The file on the server can be in any format, e.g .pdf, .exe, .doc etc
It does not matter if this is done on SSJS or in java.
I would really appreicate some code
Here is a similar question:
How to stream file from xPages?
And here is part of the Java code taken from there and completed by me (+a fix from you!). I have now tested it also and it works:
FacesContext facesContext = FacesContext.getCurrentInstance();
XspHttpServletResponse response = (XspHttpServletResponse) facesContext.getExternalContext().getResponse();
String strFileName = "myfile.txt";
String strFilePath= "c:" + File.separator + strFileName;
response.setContentType(URLConnection.guessContentTypeFromName(strFileName));
response.setHeader("Content-Disposition","attachment;filename=" + strFileName);
//File file = new File(strFilePath);
FileInputStream fileIn = new FileInputStream(strFilePath);
ServletOutputStream out = response.getOutputStream();
int iLen = 0;
byte[] btBuffer = new byte[10240]; // Not sure about optimal buffer size
while ((iLen = fileIn.read(btBuffer)) != -1) {
out.write(btBuffer, 0, iLen);
}
facesContext.responseComplete();
out.close();
You could do all this in SSJS also.
If guessContentTypeFromName does not guess it then you need to modify the definition file on server. Or if you have a limited set of file types you can place the MIME-type table in your code/application.
Here is the code I came up with to do this, def not production code.
public static byte[] grabFile(String readFile) throws IOException {
File file = new File(readFile);
ByteArrayOutputStream ous = new ByteArrayOutputStream();
InputStream ios = new FileInputStream(file);
try {
byte []buffer = new byte[4096];
int read = 0;
while ( (read = ios.read(buffer)) != -1 ) {
ous.write(buffer, 0, read);
}
} finally {
try {
if ( ous != null )
ous.close();
} catch ( IOException e) {
}
try {
if ( ios != null )
ios.close();
} catch ( IOException e) {
}
}
return ous.toByteArray();
}
public static void download() throws IOException {
byte[] data = grabFile("\\\\server\\path\\to\\file.pdf");
HttpServletResponse response = (HttpServletResponse)FacesContext.getCurrentInstance().getExternalContext().getResponse();
response.reset();
response.setContentType("application/pdf");
response.setHeader("Content-disposition", "attachment; filename=\"filename.pdf\"");
OutputStream output = response.getOutputStream();
output.write(data);
output.close();
FacesContext.getCurrentInstance().responseComplete();
}
Then just call the download method from the beforeRenderResponse of your Xpage

Is there a common way to download all types of files in jsp?

I want to download office files,pdf files,image files,zip files,dll files,exe files based on the user selection.So, I want to download these file types from jsp page.
This is jsp code snippt:
<%
String filename = "Sample1.docx";
String filepath = "e:\\temp\\";
response.setContentType("APPLICATION/OCTET-STREAM");
response.setHeader("Content-Disposition","attachment; filename=\"" + filename + "\"");
java.io.FileInputStream fileInputStream = new java.io.FileInputStream(filepath + filename);
int i;
while ((i=fileInputStream.read()) != -1) {
out.write(i);
}
fileInputStream.close();
%>
But it raising some error when downloading office files, images files.When i open the downloaded files it says "The File may be Corrupted".
Is there any common way to download all types of files in jsp?
Your problem is that the out variable in a JSP is a JspWriter, which is a character stream and so your binary files get altered. You would be much better off using a servlet directly for this particular purpose.
ok, there are some issues when downloading files from different browsers. My example takes care the handling needed in MSIE and Mozilla type of browsers
public HttpServletResponse getFile (HttpServletRequest request ,HttpServletResponse httpServletResponse, .......){
HttpServletResponse response = httpServletResponse;
InputStream in =/*HERE YOU READ YOUR FILE AS BinaryStream*/
String filename = "";
String agent = request.getHeader("USER-AGENT");
if (agent != null && agent.indexOf("MSIE") != -1)
{
filename = URLEncoder.encode(/*THIS IS THE FILENAME SHOWN TO THE USER*/, "UTF8");
response.setContentType("application/x-download");
response.setHeader("Content-Disposition","attachment;filename=" + filename);
}
else if ( agent != null && agent.indexOf("Mozilla") != -1)
{
response.setCharacterEncoding("UTF-8");
filename = MimeUtility.encodeText(/*THIS IS THE FILENAME SHOWN TO THE USER*/, "UTF8", "B");
response.setContentType("application/force-download");
response.addHeader("Content-Disposition", "attachment; filename=\"" + filename + "\"");
}
BufferedOutputStream out = new BufferedOutputStream(response.getOutputStream());
byte by[] = new byte[32768];
int index = in.read(by, 0, 32768);
while (index != -1) {
out.write(by, 0, index);
index = in.read(by, 0, 32768);
}
out.flush();
return response;
}
check this out
UPDATED
The problem is with JSP's "Out.write", which is not capable of writing byte stream...
Replaced jsp file with servlet...
The code snippet is:
protected void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
try {
String filename = (String) request.getAttribute("fileName");
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition",
"attachment;filename="+filename);
File file = new File(filename);
FileInputStream fileIn = new FileInputStream(file);
ServletOutputStream out = response.getOutputStream();
byte[] outputByte = new byte[(int)file.length()];
//copy binary contect to output stream
while(fileIn.read(outputByte, 0, (int)file.length()) != -1)
{
out.write(outputByte, 0, (int)file.length());
}
}
Now U can download all types of files....

Categories