Download file in JSP with AJAX - java

I have a simple JSP page, which contains 2 buttons: View and Export. When View button is clicked I will fetch data from DB, keep a copy into session and write an HTML code into a label with the data. Later when user clicks Export I want to generate an excel file in the server(with the data from session) and download it to clientside.
Excel file is successfully created at serverside. I am using an AJAX request from clientside to download Excel file from server.
JSP code:
try{
String filepath=ExportToExcel(session.getAttribute("InvestmentDetails"));
//Setting file to download
response.setContentType( "application/x-download");
response.setHeader("Content-Disposition","attachment; filename=\"SIPInvestment_531.xls\"");
response.setStatus(200);
InputStream in = null;
ServletOutputStream outs = response.getOutputStream();
try {
File filetodownload=new File(filepath);
response.setContentLength(Integer.parseInt(String.valueOf(filetodownload.length())));
in = new BufferedInputStream(new FileInputStream(filetodownload));
int ch;
while ((ch = in.read()) != -1) {
outs.print((char) ch);
}
}
finally {
if (in != null) in.close();
}
outs.flush();
outs.close();
}
catch(Exception ex){
str=ex.getMessage();
}
Here is the Javascript:
xmlhttp=new XMLHttpRequest();
xmlhttp.onreadystatechange=function(){
if (xmlhttp.readyState==4 && xmlhttp.status==200)
{
}
}
xmlhttp.open("POST","/SIP/rptClientInvestmentDetails.jsp?requesttype=export",false);
xmlhttp.send();
The request reaches on JSP page. And without any exception it writes to response outputstream. But no download is pop up from browser. What can be the problem?

Ajax should be used for meta-languages, not for binary files.
A simple
<a href="/SIP/rptClientInvestmentDetails.jsp?requesttype=export"
target="_blank">Export</a>
is all you need.
If you make sure you said the response.setHeader("Content-Disposition","attachment you should drop the target-attribute as BalusC suggested.

I think you can use location.href="Provide the java class function name".This will transfer the control from jsp to java function without using the ajax call

Related

Bootstrap progress bar visible when downloading file from java servlet

I want to show the BootStrap's progress bar while am downloading file from Sevlet API.
Application architecture designed like - From React JS using SuperAgent am invoking Servlet API which is responsible for writing a Excel file and it will return that Excel file to the SuperAgent to download the same.
While doing this process i want to show the BootStrap's progress bar for UX.
Please find my code below
Servlet API code for writting a Excel file and return the same to SuperAgent
try {
String reportname = "Invoice";
resp.setContentType("application/vnd.ms-excel");
resp.setHeader("Content-Disposition", "attachment; filename=" +
reportname + ".xls");
HSSFWorkbook workbook1=service.getCommercialInvoiceService(id);
ByteArrayOutputStream outByteStream = new ByteArrayOutputStream();
workbook1.write(outByteStream);
byte [] outArray = outByteStream.toByteArray();
int fileSize=outArray.length;
outStream = resp.getOutputStream();
outStream.write(outArray);
outStream.flush();
outStream.close();
resp.setHeader("Content-Length", ""+fileSize);
} catch (IOException ioe) {
throw new ServletException(ioe);
}
ReactJS method which is using SuperAgent to download file from Servlet API
handleInvoice(e) {
e.preventDefault()
var item = this.state.item;
var lines = item.order;
var request = require('superagent');
var apiBaseUrl = "api/Invoice";
var req = request.get(apiBaseUrl);
req.query({ item : item.id})
req.end(function(err,res) {
if(err) {
alert(" error"+err);
confirmAlert({
message: 'Invoice is not prepared properly.....',
confirmLabel: 'Ok',
});
}
else {
window.location= 'api/Invoice?item=' + item.id,'';
element.click();
}
});
}
I want to show the below bootstrap's progress bar while downloading the file.
<div class="progress">
<div class="progress-bar" role="progressbar" aria-valuenow="" aria-
valuemin="0" aria-valuemax="100" style="width: 60%;">
</div>
</div>
How do i integrate progress bar in ReactJS code ( SuperAgent is invoking the Java Servlet API).
Your code which writes the headers and data is as follows..
int fileSize=outArray.length;
outStream = resp.getOutputStream();
outStream.write(outArray);
outStream.flush();
outStream.close();
resp.setHeader("Content-Length", ""+fileSize);
Note that the content length is being set after the output stream has been written to. HTTP responses consist of a series of headers followed the content, which you write to via the OutputStream. Here you have simply set the content length after streaming the content. So this value is not sent at the start of the response.
The content length of the output is not mandatory (it might not be known by the process streaming it). But of course you can't produce a progress bar unless you know the length of the data. Simply set the content length before writing the data so it makes it into the response headers.
int fileSize=outArray.length;
resp.setHeader("Content-Length", ""+fileSize);
outStream = resp.getOutputStream();
outStream.write(outArray);
outStream.flush();
outStream.close();

Getting the jsp source code appended with the file content when I download files

I am working on a File upload/download functionality, in Java using Struts2 framework, where we are uploading to and downloading from a remote server path. All seems to work fine when I check the functionality at my local machine with a local path as the destined path from where i am downloading and to which am uploading the files of any format. The development environment has JBoss server.
But when I run the same over at the prod env, where the application is deployed in Weblogic server, files of .txt,.csv,.html (basically text format files) have my jsp source code appended to the file content.
Below is the code that I have used for downloading:
BufferedOutputStream bout=null;
FileInputStream inStream = null;
byte[] buffer = null;
try {
inStream = new FileInputStream(path+File.separator+filename);
buffer = new byte[8192];
String extension = "";
int pos = filename.lastIndexOf(".");
if (pos > 0)
extension = filename.substring(pos+1);
int bytesRead = 0, bytesBuffered = 0;
response.setContentType("application/octet-stream");
response.setHeader("content-disposition", "attachment; filename="+ filename);
bout = new BufferedOutputStream(response.getOutputStream());
while((bytesRead = fistrm.read(buffer)) > -1){
bout.write(buffer, 0, bytesRead);
bytesBuffered += bytesRead;
if(bytesBuffered > 1048576){
bytesBuffered = 0;
bout.flush();
}
}
} catch (IOException e) {
log.error(Logger.getStackTrace(e));
} finally {
if(bout!=null){
bout.flush();
bout.close();
}
if(inStream!=null)
inStream.close();
}
I have tried using different response content types with respect to the extension, but it was of no help.
Seems like the outputstream has the jsp source code in it even before writing from the inputstream.
Can anyone please suggest a solution and explain why is this happening ?
It is happening because you are writing directly in the outputstream, and then returning a struts result, that is your JSP. You are using an action as if it would be a servlet, which is not.
In Struts2, to achieve your goal, you need to use the Stream result type, as described in the following answers:
https://stackoverflow.com/a/16300376/1654265
https://stackoverflow.com/a/16900840/1654265
Otherwise, if you want to bypass the framework mechanisms and manually write to the outputStream by yourself (there are very rare cases in which it is useful, like downloading dynamically created ZIP), then you must return the NONE result.
Returning ActionSupport.NONE (or null) from an Action class method causes the results processing to be skipped. This is useful if the action fully handles the result processing such as writing directly to the HttpServletResponse OutputStream.
But I strongly suggest you to go with the Stream result, the standard way.

Display image using angular js

I want to display image on the page that is returned by the java controller.
Java controller:
public FileSystemResource RetrieveLogo(#PathVariable("UniqueCode") String Code){
// get image file
return fileSystemResource;
}
at java script controller, I make a service call to get the image .
Javascript controller:
$scope.logo = function() {
rest.retrieveLogoForMerchant({id: 'abcd'}).$promise.then(function(data) {
console.log("-------------success--------- " + angular.toJson(data));
$scope.logoImage = angular.toJson(data);
});
}
Here the console prints -
{"0":"�","1":"�","2":"�","3":"�","4":"\u00.......etc}
On Html page
<img ng-src="{{logoImage}}" height="100" width="100"/>
On the page image displays blank and gives error in the console that -
http://localhost:9090/%7B%220%22:%22%EF%BF%BD%22,%221%22:%22%EF%BF%BD%22,%2…22%EF%BF%BD%22,%22246%22:%22\u0007%22,%22247%22:%22\u0014%22,%22248%22:%22 400 (Bad Request)
Suggest me ,that how can I display image properly.
Thanks
Try removing the the angular.toJSON method here:
$scope.logoImage = angular.toJson(data);
And also
I think you are loading image through binary data append proper image encoding
to the data Eg: ng-source={{data:image/png;base64........}}
You need to set the right content type in response inside your Java controller, see below function
public void displayImage(HttpServletResponse response, byte[] imageArray) throws ServletException, IOException {
System.out.println("Inside display Image function");
if (imageArray != null && imageArray.length > 0) {
response.setHeader("Pragma", "no-cache");
response.setHeader("Cache-Control", "no-cache");
response.setDateHeader("Expires", 0);
System.out.println("Image Array is not null :" + imageArray);
response.setContentType("image/jpeg");
OutputStream out = response.getOutputStream();
out.write(imageArray);
out.flush();
out.close();
} else {
System.out.println("Image is null");
}
}
Than you need to make sure append that appropriate header before data content while setting it to img tag.. #Naveen has already pointed about it in his answer. Basically you need to have something like this
<img src="data:image/png;base64,/*Your data part goes here*//>
You also need to encode the stream to Base64 before assigning it to img. I had below line in my jsp you can alter it to suit your need..
<img id="userProfileImg" height="150px" width="150px" name="userProfileImg" alt="../img/user_default_pic.png" src='data:image/jpg;base64,<%=Base64.encode(/*Blob data returned from database*/)%>'/>
Why don't you get the URL of the image via http (ajax call) and on success $scope.logoImage = data. data is the URL of the image retrieved via http.

unable save image in jsp

I'm unable to save a Data URI in JSP. I am trying like this, is there any mistake in the following code?
<%# page import="java.awt.image.*,java.io.*,javax.imageio.*,sun.misc.*" %>
function save_photo()
{
Webcam.snap(function(data_uri)
{
document.getElementById('results').innerHTML =
'<h2>Here is your image:</h2>' + '<img src="'+data_uri+'"/>';
var dat = data_uri;
<%
String st = "document.writeln(dat)";
BufferedImage image = null;
byte[] imageByte;
BASE64Decoder decoder = new BASE64Decoder();
imageByte = decoder.decodeBuffer(st);
ByteArrayInputStream bis = new ByteArrayInputStream(imageByte);
image = ImageIO.read(bis);
bis.close();
if (image != null)
ImageIO.write(image, "jpg", new File("d://1.jpg"));
out.println("value=" + st); // here it going to displaying base64 chars
System.out.println("value=" + st); //but here it is going to displaying document.writeln(dat)
%>
}
}
Finally, the image is not saved.
I think you didn't get the difference between JSP and JavaScript. While JSP is executed on the Server at the time your browser requires the web page, JavaScript is executed at the Client side, so in your browser, when you do an interaction that causes the JavaScript to run.
You Server (eg Apache Tomcat) will firstly execute your JSP code:
String st = "document.writeln(dat)";
BufferedImage image = null;
byte[] imageByte;
BASE64Decoder decoder = new BASE64Decoder();
imageByte = decoder.decodeBuffer(st);
ByteArrayInputStream bis = new ByteArrayInputStream(imageByte);
image = ImageIO.read(bis);
bis.close();
if (image != null)
ImageIO.write(image, "jpg", new File("d://1.jpg"));
out.println("value=" + st);
System.out.println("value=" + st);
As you can see, nowhere is the value of st changed. Your broser will receive the following snippet from your server:
value=document.writeln(dat);
Since your browser is the one that executes JavaScript, he will execute it and show the Base64-encoded Image - but your server won't.
For the exact difference, read this article.
To make the code working, the easiest way is to redirect the page:
function(data_uri)
{
// redirect
document.location.href = 'saveImage.jsp?img='+data_uri;
}
Now, you can have a JSP-page called saveImage.jsp that saves the Image, and returns the webpage you had already, and write the dara_uri into the element results.
Another, but more difficult way is to use AJAX. Here is an introduction to it.
You are trying to use JavaScript variables in Java code. Java code is running on your server, while Javascript code runs in user's browser. By the time JavaScript code executes, your Java code has already been executed. Whatever you're trying to do, you have to do it in pure javascript, or send an AJAX call to your server when your Javascript code has done it's thing.

How to upload a zip file using Java?

I trying to upload a zip file. In my project i am using DWR in the client side and Java in server side. As i have seen in DWR tutorials for uploading data(Its not in their website. They are providing it with dwr.rar bundle) they getting input by the below lines.
var image = dwr.util.getValue('uploadImage');
var file = dwr.util.getValue('uploadFile');
var color = dwr.util.getValue('color');
dwr.util.getValue() is a utility to get the value of any element, in this case a file object.//Mentioned in the tutorial.
So, i get a zip file using that utility by the below code.
Javascript:
function uploadZip(){
var file = dwr.util.getValue("uploadFile");
dwr.util.setValue("uploadFile", null);
DataUpload.uploadData(file, function(data){
if(data != null){
$("#zipURL").html("<p>Upload Completed!!!</p>");
$("#zipURL").append("Location: "+data.path2);
}
});
}
HTML:
<html>
<head>ZIP Uploader
</head>
<body>
<table>
<tr><td>Select File: </td><td><input type="file" id="uploadFile" /></td>
<tr><td><input type="button" value="Upload" onclick="uploadZip()" /></td></tr> </table>
<div id="result"><span id="imgURL"></span>
<span id="zipURL"></span></div>
</body>
</html>
The Java Code is:
public class DataUpload {
private static String DATA_STORE_LOC = "D:/BeenodData/Trials/";
public Path uploadData(InputStream file) throws IOException{//In the tutorial the
//parameters are in type of BufferedImage & String.
//They used it for image and text file respectively.
//In an another example(out of DWR site) they used InputStream for receiving
//image
try {
byte[] buffer = new byte[1024];
int c;
File f2 = new File(DATA_STORE_LOC+dat+".zip");
path.setPath2(DATA_STORE_LOC+dat+".zip");
FileOutputStream fos = new FileOutputStream(f2);
c = file.read();
System.out.println(c);
while ((c = file.read()) != -1) {
fos.write(c);
}
file.close();
fos.close();
} catch (IOException e) {
// TODO Auto-generated catch block
e.printStackTrace();
}
return path;
}
This code runs without error. But the output is a Empty zip file. I know i doing something wrong. I unable to find that.
Actually, i am receiving a zip file as
InputStream.
How should i have to write a
InputStream(a zip file) to a zip.file
using java?
What will happen if i set the java
method parameter as ZipFile file? I
didnt tried it, yet because, i am
still searching a good tutorial to
learn about it.
Any Suggestion or Links would be more appreciative!!!!!
Thanks in Advance!!!
Here you have 2 examples about creating a ZIP file:
http://www.java2s.com/Tutorial/Java/0180_File/0601_ZipOutputStream.htm
Here is an example about reading a ZIP file:
http://www.kodejava.org/examples/334.html
I have also implemented the Same kind of backend Code in Java, and I was facing the same Issue of Zip file being made, but its content being empty.
Later I found that the Request I was making to API, in that the file I was Attaching was not in --data-binary format. So, I then made the request in this Format.
curl --data-binary #"/mnt/c/checknew.zip" http://localhost/api/upload
I am not sure what request format you are making either in multipart/form-data or Base-64 encoded.
My code worked when I made a Base-64 encoded Request (i.e --data-binary)

Categories