Servlet writing file contains binary at the end - java

I have a servlet to let user download a file from server. The original file is human readable, but the downloaded file alwyas contains binary content at the end of the file.
HttpSession session = request.getSession(true);
String fileName = session.getAttribute("download").toString();
System.out.println("Download file " + fileName);
File file = new File(fileName);
FileInputStream fileIn = new FileInputStream(file);
response.setContentType("text/plain");
response.setHeader("Content-Disposition", "attachment;filename=" + file.getName());
ServletOutputStream out = response.getOutputStream();
byte[] bytes = new byte[BYTES_DOWNLOAD];
while (fileIn.read(bytes, 0, BYTES_DOWNLOAD) != -1) {
out.write(bytes, 0, BYTES_DOWNLOAD);
}
out.flush();
out.close();
Thanks in advance.

Small bug in your code:
byte[] bytes = new byte[BYTES_DOWNLOAD];
int count;
while ( (count = fileIn.read(bytes)) != -1) {
out.write(bytes, 0, count);
}

What binary content do you see? Is it perhaps the line endings in the file, if any?

Related

getOutputStream() has already been called for this response for ServletOutputStream outputStream = response.getOutputStream();

Getting exception as getOutputStream() has already been called for this response when using
ServletOutputStream outputStream = response.getOutputStream();
in my code.
Here is the sample code. First i'm placing the input file in my local path which is a svg image. After that svg is converted into png and get downloaded from browser.
{ //code to write image into local path
File filesvg = new File(inFile);
svg = svg.replace("1e-006","0.000001");
FileWriter writer = new FileWriter(filesvg);
writer.write(svg);
writer.close();
//here some lines of code to convert to png
return outFile;
}
//Code to download image from browser.
response.setContentType("application/octet-stream");
response.setHeader("Content-Disposition",
"attachment;filename=\"" + filename + ext + "\"");
FileInputStream fileIn = new FileInputStream(file);
ServletOutputStream outputStream =
response.getOutputStream();
byte[] outputByte = new byte[4096];
int byteRead;
while ((byteRead = fileIn.read(outputByte, 0, 4096))
!= -1) {
outputStream.write(outputByte, 0, byteRead);
}
fileIn.close();
outputStream.flush();
outputStream.close();

Convert BLOB to PDF

I have a BLOB file which I have got from the DB team. I know that its a PDF document (I opened using Notepad++ and I could see the file name) and I need to convert the same using java. I have checked for few examples and I couldn't find any example where the BLOB file itself is taken as an input instead of taking directly from the DB (Resultset). Can anyone please give some pointers as to how I can accomplish this?
Thanks in advance!
I have tried below,
File file = new File("C:/Users/User1/Desktop/0LK54E33K1477e2MCEU25JV0G8MG418S007N45JU.BLOB0");
FileInputStream fis = new FileInputStream(file);
//System.out.println(file.exists() + "!!");
//InputStream in = resource.openStream();
ByteArrayOutputStream bos = new ByteArrayOutputStream();
byte[] buf = new byte[1024];
try {
for (int readNum; (readNum = fis.read(buf)) != -1;) {
bos.write(buf, 0, readNum); //no doubt here is 0
//Writes len bytes from the specified byte array starting at offset off to this byte array output stream.
System.out.println("read " + readNum + " bytes,");
}
} catch (IOException ex) {
//Logger.getLogger(genJpeg.class.getName()).log(Level.SEVERE, null, ex);
}
byte[] bytes = bos.toByteArray();
//below is the different part
File someFile = new File("C:/Users/User1/Desktop/Test.pdf");
FileOutputStream fos = new FileOutputStream(someFile);
fos.write(bytes);
fos.flush();
fos.close();

Download link to CSV file in the mail using spring boot

I am generating csv in my code, It takes some time to generate. So, I am sending an email with link once the csv file is generated. When I click that, getting 404 not found error. When I have the same link in the html, I am able to download it. Any insight or sample to refer
Sample Link -http://localhost:9090/api/report/file?fileName=filename.csv
Java code to download the report
#RequestMapping(value = "api/report/file")
public void downloadCSV(HttpServletResponse response, #RequestParam("fileName") String fileName) throws IOException {
File file = new File(fileName);
InputStream is = new FileInputStream(file);
response.setContentType("application/octet-stream");
// Response header
response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");
// Read from the file and write into the response
OutputStream os = response.getOutputStream();
byte[] buffer = new byte[1024];
int len;
while ((len = is.read(buffer)) != -1) {
os.write(buffer, 0, len);
}
os.flush();
os.close();
is.close();
}
Add GET method to this mapping: #RequestMapping(value = "api/report/file")

Android File To Base64 using streaming sometimes missed 2 bytes

i am writing to ask for the proper solution for solving the following difficulties:
I am required to encode the file in Base64 format, and there is no way for me to make the file small, as a result, i will surely suffered from OutOfMemory Exception, that why i used Streaming approach for solving it.
After the file is encoded, i have decoded it immediately by code and also online-tools. The decoded content was found missing 2 bytes at the end of the file sometimes, but not always. It did affected further processing to the file.
Hope someone could help and may be caused by an idiot mistake. Still thanks.
Here is the Code:
FileOutputStream fout = new FileOutputStream(path + ".txt");
//this is for printing out the base64 content
FileInputStream fin = new FileInputStream(path);
System.out.println("File Size:" + path.getTotalSpace());
ByteArrayOutputStream os = new ByteArrayOutputStream();
Base64OutputStream base64out = new Base64OutputStream(os,Base64.NO_WRAP);
byte[] buffer = new byte[3 * 512];
int len = 0;
while ((len = fin.read(buffer)) >= 0) {
base64out.write(buffer, 0, len);
}
System.out.println("Encoded Size:" + os.size());
String result = new String(os.toByteArray(), "UTF-8");
fout.write(os.toByteArray());
fout.close();
base64out.close();
os.close();
fin.close();
return result;
Here is the solution that works in the case of using Base64OutputStream. I will explain some of them after code:
Here is the Code:
FileOutputStream fout = new FileOutputStream(path + ".txt");
FileInputStream fin = new FileInputStream(path);
System.out.println("File Size:" + path.length());
ByteArrayOutputStream os = new ByteArrayOutputStream();
Base64OutputStream base64out = new Base64OutputStream(os,Base64.NO_WRAP);
byte[] buffer = new byte[3 * 512];
int len = 0;
while ((len = fin.read(buffer)) >= 0) {
base64out.write(buffer, 0, len);
}
System.out.println("Encoded Size:" + os.size());
base64out.flush();
base64out.close();//this did the tricks. Please see explanation.
String result = new String(os.toByteArray(), "UTF-8");
fout.write(os.toByteArray());
fout.flush();
fout.close();
os.close();
fin.close();
return result;
Actually, after using the suggestion from Dawnkeeper by added flush(), i have moved one line of code only.
The tricks is did in the base64out.close() before processing any data. As closing the Base64OutputStream might write Ending Padding of Base64 to the Output.
I got my idea from org.apache.myfaces.trinidad.util.Base64OutputStream close() method. That's why i tried.
It might seems strange closing the OutputStream before data processing, but it only close Base64OutputStream but not ByteArrayOutputStream at the same time in this case. Therefore, the data could still retrieve from ByteArrayOutputStream.
Thanks Dawnkeeper efforts, and hope this question could helps other suffered in OutOfMemory Exception.
Your streams should be flushed before using them for other operations and before closing them:
FileOutputStream fout = new FileOutputStream(path + ".txt");
//this is for printing out the base64 content
FileInputStream fin = new FileInputStream(path);
System.out.println("File Size:" + path.length()); // path.getTotalSpace() is the filesystem size
ByteArrayOutputStream os = new ByteArrayOutputStream();
Base64OutputStream base64out = new Base64OutputStream(os,Base64.NO_WRAP);
byte[] buffer = new byte[3 * 512];
int len = 0;
while ((len = fin.read(buffer)) >= 0) {
base64out.write(buffer, 0, len);
}
System.out.println("Encoded Size:" + os.size());
base64out.write(System.lineSeparator().getBytes());
base64out.flush(); // to be sure that everything is in the byte array
String result = new String(os.toByteArray(), "UTF-8");
fout.write(os.toByteArray());
fout.flush(); // make sure everything is written
fout.close();
base64out.close();
os.close();
fin.close();
System.out.println("new File Size:" + new File(path + ".txt").length()); // prints out the size of the finished file
return result;

IE8 asks to Open/Save twice on .xls file

I'm generating an Excel document via Servlet. When I send the response back to the client (IE8), the "Open/Save" dialog pops up but requires users to click a choice twice before taking action. This doesn't happen in Firefox. I have no idea why this is occurring. Below is the relevant code that creates the appropriate streams.
result contains the Excel XML.
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment;filename=TestFile.xls");
InputStream in = new ByteArrayInputStream(result.toString().getBytes("UTF-8"));
ServletOutputStream out = response.getOutputStream();
try
{
byte[] outputByte = new byte[4096];
while(in.read(outputByte, 0, 4096) != -1)
out.write(outputByte, 0, 4096);
}
finally
{
in.close();
out.flush();
out.close();
}
EDIT
I have noticed that waiting 5+ seconds before clicking an option works just fine. It seems to only ask twice when immediately clicking an option.
This code works well for every type of file in my application
InputStream in = blob.getBinaryStream();
// Output the blob to the HttpServletResponse
String codedfilename = "";
//this code resolves the issue with the encoding of the downloaded filename
String agent = request.getHeader("USER-AGENT");
if (null != agent && -1 != agent.indexOf("MSIE"))
{
codedfilename = URLEncoder.encode(/*here goes the filename*/, "UTF8");
response.setContentType("application/x-download");
response.setHeader("Content-Disposition","attachment;filename=" + codedfilename);
}
else if (null != agent && -1 != agent.indexOf("Mozilla"))
{
response.setCharacterEncoding("UTF-8");
//It does not seem to make a difference whether Q or B is chosen
codedfilename = MimeUtility.encodeText(rset.getString("FILE_NAME"), "UTF8", "B");
response.setContentType("application/force-download");
response.addHeader("Content-Disposition", "attachment; filename=\"" + codedfilename + "\"");
}
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();
try it and let us know

Categories

Resources