I am using Tomcat 8 and I have functionality to download large files from tomcat server places in context docbase folder.
Below is the piece of code I am using the file to download:
PrintWriter out = response.getWriter();
response.setContentType("APPLICATION/OCTET-STREAM");
response.setHeader("Content-Disposition",
"attachment; filename=filename);
FileInputStream fileInputStream = new FileInputStream("filepath");
int i;
while ((i=fileInputStream.read()) != -1) {
out.write(i);
}
fileInputStream.close();
out.close();
When I download a file it is downloading with a speed of 65KB/sec
from the save server. If I place the same file in Apache server and try to download the download speed is 135KB/sec.
Could someone help me speed up the file download from Tomcat?
The problem is that reading and writing a byte at a time to unbuffered streams is very inefficient. Looking at this previous answer and adapting it to your code, we could use:
// Assume ServletResponse response
ServletOutputStream servletOutputStream = response.getOutputStream();
response.setContentType("APPLICATION/OCTET-STREAM");
response.setHeader("Content-Disposition",
"attachment; filename=filename);
FileInputStream fileInputStream = new FileInputStream("filepath");
// Choose a bigger value if you want
byte[] buffer = new byte[4096];
int n;
while ((n = fileInputStream.read(buffer) != -1)
{
servletOutputStream.write(buffer, 0, n);
}
fileInputStream.close();
servletOutputStream.close();
The above should be very efficient and hopefully equal or surpass your reported Apache speeds.
Related
I want to open my servlet which basically checks my permissions and if allowed, shows me a picture like it would be a real jpeg. My code so far:
File file = new File("C:/test.jpeg");
FileInputStream fis = new FileInputStream(file);
byte imageBytes[] = new byte[(int) file.length()];
response.setContentType("image/jpeg");
response.setContentLength(imageBytes.length);
response.getOutputStream().write(imageBytes);
response.getOutputStream().flush();
But somehow the image it tries to show me in the browser is corrupted. I already checked that the file exists, as the image.length is not zero. What did I do wrong?
You should start using the newer NIO.2 File API that was added in Java 7, mostly the Files class, because it makes the job much easier.
Option 1: Load file into byte[]
byte[] imageBytes = Files.readAllBytes(Paths.get("C:/test.jpeg"));
response.setContentType("image/jpeg");
response.setContentLength(imageBytes.length);
try (OutputStream out = response.getOutputStream()) {
out.write(imageBytes);
}
Option 2: Stream the file without using a lot of memory (recommended)
Path imageFile = Paths.get("C:/test.jpeg");
response.setContentType("image/jpeg");
response.setContentLength((int) Files.size(imageFile));
try (OutputStream out = response.getOutputStream()) {
Files.copy(imageFile, out);
}
I have a requirement to download excel to the excel file on client side using servlet. I am first creating an excel by fetching the values from mysql table and then downloading it. The excel is getting created in the path provided but I am unable to download it. Please find my code below for downloading:
String exportFileName = ResourceConstants.EXCEL_FILEPATH+"/"+ResourceConstants.EXCEL_FILENAME;
FileInputStream inf = null;
response.setContentType("application/vnd.ms-excel");
response.addHeader("content-disposition",
"attachment; filename=" + exportFileName);
response.setHeader("Pragma", "public");
response.setHeader("Cache-Control", "no-store");
response.addHeader("Cache-Control", "max-age=0");
final int size = 1024;
try{
inf = new FileInputStream(exportFileName);
response.setContentLength(inf.available());
final byte[] buffer = new byte[size];
ServletOutputStream os = null;
os = response.getOutputStream();
int length = 0;
while ((length = inf.read(buffer)) != -1) {
os.write(buffer, 0, length);
}
inf.close();
os.flush();
os.close();
} catch (final FileNotFoundException e) {
LOGGER.error("FileNotFoundException occurred in download excel method!!!"+e.getMessage());
}
Please help me understand if I am doing something wrong here.
Need a servlet to download a file from path like /home/Bureau.. in jee gwt
I used this but isn't work
and I went to download all file's type image
String filePath = request.getParameter("file");
String fileName = "test";
FileInputStream fileToDownload = new FileInputStream(filePath);
// ServletOutputStream output = response.getOutputStream();
response.setHeader("Content-Type", "image/png");
//response.setContentType("image/png");
response.setHeader("Content-Disposition", "attachment; filename=\"" + fileName + ".png\"");
// response.setContentLength(fileToDownload.available());
int readBytes = 0;
byte[] buffer = new byte[10000];
while ((readBytes = fileToDownload.read(buffer, 0, 10000)) != -1) {
//output.write(readBytes);
response.getOutputStream().write(readBytes);
}
response.getOutputStream().close();
fileToDownload.close();
fileToDownload.close();
The problem is at below line where you are writing no of bytes not actual bytes. Here readBytes represents no of bytes read at a time where as buffer contains actual bytes that is read.
response.getOutputStream().write(readBytes);
Try
OutputStream outputStream = response.getOutputStream();
while ((readBytes = fileToDownload.read(buffer)) != -1) {
outputStream.write(buffer,0,readBytes);
}
outputStream.close();
I suggest you to call response.getOutputStream() single time.
Your code will give you IndexOutOfBoundsException if the size of the file is less than 10000 bytes because of below line
fileToDownload.read(buffer, 0, 10000)
Change it to
fileToDownload.read(buffer)
Use ServletContext to get file path.
ServletContext context = getServletContext();
For more info have a look at below posts:
Writing image to servlet response with best performance.
How do I return an image from a servlet using ImageIO?
I want to make a provision to download all file types...Is there any way to download any file format in jsp...
My code snippet:
String filename = (String) request.getAttribute("fileName");
response.setContentType("APPLICATION/OCTET-STREAM");
String disHeader = "Attachment";
response.setHeader("Content-Disposition", disHeader);
// transfer the file byte-by-byte to the response object
File fileToDownload = new File(filename);
response.setContentLength((int) fileToDownload.length());
FileInputStream fileInputStream = new FileInputStream(fileToDownload);
int i = 0;
while ((i = fileInputStream.read()) != -1) {
out.write(i);
}
fileInputStream.close();
If I specify setContentType as APPLICATION/OCTET-STREAM, pdf, text, doc files are getting downloaded.... But the problem is with image files...
What is problem with image files? I want to download all image file types...
I searched similar questions but could not find proper answer...
Thanks...
Finally I somehow managed to do this...
The problem is with JSP's "Out.write", which is not capable of writing byte stream...
I 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 I can download all types of files....
Thanks for the responces :)
Check the following link ,
JSP download - application/octet-stream
Might help you to resolve the issue.
for images you should use setContentType(image/jpg).you can checkout this link for mime types
http://webdesign.about.com/od/multimedia/a/mime-types-by-content-type.htm
i have a project where i'm dealing with restful web service, especially need to return images for android client, when client is entering the "gallery" he need to get a root collection which have to return all of folders and file(images) from static folder on running server. Can someone help with this? How can i return images that could be accessed by client for detailed view?
You only need to getHttpServletRequest and HttpServletResponse type of object and apply below code -
String filePath = request.getParameter(YOUR_FILE_PATH_PARAMETER");
String filePath = filePath;
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition", "attachment;filename="
+ "YOUR_FILE_NAME");
// Get it from file system
FileInputStream in = new FileInputStream(new File(filePath));
ServletOutputStream out = response.getOutputStream();
byte[] outputByte = new byte[4096];
// copy binary content to output stream
while (in.read(outputByte, 0, 4096) != -1) {
out.write(outputByte, 0, 4096);
in.close();
out.flush();
out.close();