Can we Download a CSV file using Http Post? - java

So , I have some thing like this in the back end.
response.setContentType("text/csv; name=" + fileName);
response.addHeader("content-disposition", "attachment; filename=\"" + fileName + "\"");
try {
final String csvBuilder = this.reportService.tripSummaryCsvBuilder(trips);
response.getOutputStream().write(csvBuilder.getBytes());
} catch (Exception e) {
logger.error("downloadTripSummary() - Unexpected exception: ", e);
throw new ServerErrorException("download trip summary csv file failed");
}
So, All the back end code works fine. But the only problem here is I need to send like an ArrayList of 1000 objects to server , based on each element inside the arraylist the csv is built on the server.
If its a normal Http Get , it will works fine . But in this case, i need to use POST because I cant send 1000 objects as part of url.
I am using angular js on UI side . Could some one please assist me on how to do this ?
I have tried to use $http.post call using an ajax service in agular js, but the service is not able to pop up the window to save the file once the response is received.

http://plnkr.co/edit/N5bMq7dJ4YPJrppR1PPt
Check this plunker, with fileSaver u can save as fileName.
I found it here

Related

How to download multiple files from a single directory in Java

How to download all files in the file directory when clicking the export or download at the same time?
At present, all the files in the file directory have been obtained, then all the files are placed in the list, and then the stream is written after traversing all the files. However, when importing the second file, it will report cannot reset buffer after response has been committed
The source of the problem is in this code: // response.reset();
Code:
String filePath = "/code/data/";
// Get all file addresses of the directory
List<String> filePathList = getFilePath(filePath);
//Create thread pool
for (String str : filePathList){
download(request, response, str);
}
private void download(HttpServletRequest request,
HttpServletResponse response,String filePath) {
File file = new File(filePath);
//Gets the file name.
String fileName = file.getName();
InputStream fis = null;
try {
fis = new FileInputStream(file);
request.setCharacterEncoding("UTF-8");
String agent = request.getHeader("User-Agent").toUpperCase();
if ((agent.indexOf("MSIE") > 0) || ((agent.indexOf("RV") != - 1) &&
(agent.indexOf("FIREFOX") == -1))) {
fileName = URLEncoder.encode(fileName, "UTF-8");
} else {
fileName = new String(fileName.getBytes("UTF-8"), "ISO8859-1");
}
// response.reset();
response.setCharacterEncoding("UTF-8");
response.setContentType("application/force-download");
// Set forced download not to open
response.addHeader("Content-Disposition",
"attachment; filename=" + fileName);
response.setHeader("Content-Length", String.valueOf(file.length()));
byte[] b = new byte[1024];
int len;
while ((len = fis.read(b)) != - 1) {
response.getOutputStream().write(b, 0, len);
}
response.flushBuffer();
fis.close();
} catch (IOException e) {
throw new RuntimeException(e);
}
}
}
What are the good solutions Thanks
I have not read your code in detail because the bad formatting makes my head hurt.
However, from a superficial reading, it looks like this server-side code is trying to deliver multiple files in response to a single HTTP request.
AFAIK, that is not possible. The HTTP request / response model does not support this. It certainly does not allow a servlet to:
change response headers after the response output stream has been opened
do anything after the response output stream has been closed.
(Your code appears to be trying to do both of those things!)
So, you have to do it differently. Here are some possibilities:
On the server side, assemble all of the files to be downloaded into (say) a temporary ZIP file and then send that. Leave it to the user to unpack the ZIP file ... or not ... as they want.
This is often the best approach. Imagine how annoyed you would be if a few thousand separate files unexpectedly landed in your web browser's Downloads folder.
As 1. and also do something on the client side to transparently unpack the files from the ZIP and put them in the right place in the client's file system.
The "something" could be custom javascript embedded in the web page, or a custom client implemented in Java ... or any other language. (But in the former case, there may be a security issue in allowing sandboxed javascript to write files in arbitrary places without the user confirming each file ... tedious.)
You might be able to send a "multipart" document as the response. However from what I have read, most browsers don't support multipart for downloads; e.g. some browsers will discard all but the last part. (Note: multipart is not designed for this purpose ...)
Change things so that an HTTP request only downloads one file at a time from the directory, and add some client-side stuff to 1) fetch a list of files from the server and iterate the list, fetching each file.
See also: Download multiple files with a single action

open pdf file with sessionAsSigner

I have a database where the user doesn't has access to.
Still I can go to the database and "read" the documents with for example
var db:NotesDatabase = sessionAsSigner.getDatabase("","somedir/some.nsf");
In this database there's a pdf file I would like to open or download. I have the filename and the unid . If the user had acces to the database I could do it with
http(s)://[yourserver]/[application.nsf] /xsp/.ibmmodres/domino/OpenAttachment/ [application.nsf]/[UNID|/$File/[AttachmentName]?Open
How can I do it with sessionAsSigner without putting a $PublicAccess=1 field on the form ?
edit:
the pdf file is stored as attachment in a richtextfield
second edit
I'm trying to use the XSnippet from Naveen and made some changes
The error message I get is : 'OutStream' not found
The code I tried is :
response.reset();
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "inline; filename=" + zipFileName);
var embeddedObj:NotesEmbeddedObject = null;
var bufferInStream:java.io.BufferedInputStream = null;
var outStream:java.io.OutputStream = response.getOutputStream();
embeddedObj = downloadDocument.getAttachment(fileName);
if (embeddedObj != null) {
bufferInStream = new java.io.BufferedInputStream(embeddedObj.getInputStream());
var bufferLength = bufferInStream.available();
var data = new byte[bufferLength];
bufferInStream.read(data, 0, bufferLength); // Read the attachment data
ON THE NEXT LINE IS THE PROBLEM
OutStream.write(data); // Write attachment into pdf
bufferInStream.close();
embeddedObj.recycle();
}
downloadDocument.recycle();
outStream.flush();
outStream.close();
facesContext.responseComplete();
Create an XAgent (= XPage without rendering) which takes datebase + documentid + filename as URL parameters and delivers the file as response OutputStream.
The URL would be
http(s)://[yourserver]/download.nsf/download.xsp?db=[application.nsf]&unid=[UNID]&attname=[AttachmentName]
for an XAgent download.xsp in a database download.nsf.
The code behind the XAgent runs as sessionAsSigner and is able to read the file even the user itself has no right to access file's database.
Use Eric's blog (+ Java code) as a starting point. Replace "application/json" with "application/pdf" and stream pdf file instead of json data.
As an alternative you can adapt this XSnippet code from Thomas Adrian. Use download() together with grabFile() to write your pdf-File to OutputStream.
Instead of extracting attachment file to path and reading it from there you can stream the attachment right from document to response's OutputStream. Here is an XSnippet from Naveen Maurya as a good example.
If you can get the PDF file as a stream, you should be able to use the OutputStream of the external context's response.
Stephan Wissel has a blog posting about writing out an ODF file so you should be able to cut that up as a starting point.
http://www.wissel.net/blog/d6plinks/SHWL-8248MT
You already have the db so, you will just need to know the UNID of the document.
var doc = db.getDocumentByUNID(unid) 'unid is a supplied param
var itm:RichTextItem = doc.getFirstItem("Body") 'assuming file is in body field
Once you have the itm, you can loop round all of the embeddedObjects and get the pdf file. At this point, I don't know if you can stream it directly or if you have to detach it, but assuming you detach it, you will then use something like this.
File file = new File("path to file");
FileInputStream fileIn = new FileInputStream(file);
Don't forget to clean up the temporarily detached file

Download statistics for a remote file

The issue I am struggling with now is the following. I have a zip archive on a remote server. The eclipse plug-in I have developed downloads this archive using the suggestion from this forum:
//Connect readable channel to the URL
ReadableByteChannel rbc = Channels.newChannel(libraryUrl.openStream());
//Create local file
FileOutputStream fos = new FileOutputStream(libraryZipPath);
//Download the remote archive to the local file
fos.getChannel().transferFrom(rbc, 0, libraryUrl.openConnection().getContentLength());
//Close channel
fos.close();
I have an html file at the server that counts visit statistics for the web-page. The javascript that does counting is as follows:
var data = '&r=' + escape(document.referrer) + '&n=' + escape(navigator.userAgent)
+ '&p=' + escape(navigator.userAgent) + '&g=' + escape(document.location.href);
if (navigator.userAgent.substring(0,1)>'3')
data = data + '&sd=' + screen.colorDepth + '&sw=' + escape(screen.width+'x'+screen.height);
document.write('<a href="http://www.1freecounter.com/stats.php?i=89959" target=\"_blank\">');
document.write('<img alt="Free Counter" border=0 hspace=0 '+'vspace=0 src="http://www.1freecounter.com/counter.php?i=89959' + data + '">');
document.write('</a>');
The question is: Is it somehow possible to use this javascript or html file with it to count the download statistics for the archive file?
You are using a third party webcounter which is embedded as a graphic in your website. When the users browser loads this graphic, the third party server notices the access and increments the counter.
This doesn't work for binary downloads, because when a binary file is downloaded, the webcounter graphic isn't requested.
What you could try is to make your Java program also download the counter graphic when it downloads the binary file. Make sure to pass the URL of the zip archive as Referrer HTTP header to the image download so that the script on the server counts it as access to it. You will have to use the URLConnection class in order to set custom HTTP headers like Referrer.
Thank you for the reply, Philipp!
I have figured out how to make it work in a very simple way. Let us consider a counter in the example above ("http://www.1freecounter.com/stats.php?i=89959"). The counter by that address takes 6 parameters in total:
r - document referrer,
n and p are user agent, which consists of a browser name, OS name, OS ver, browser ver etc.,
g is the location,
sd and sw are the colour depth and the screen size (we can skip these two for a binary file).
Then, we form a string for a counting request. For instance,
String cntURL = "http://www.1freecounter.com/counter.php?i=89959&r="+
URLEncoder.encode("some string for a referrer","UTF-8") + "&n="+
URLEncoder.encode("browser name (OS name OS version) browser version", "UTF-8")+"&p="+
URLEncoder.encode("the same as above", "UTF-8")+"&g=<location string>";
Notice that the parameters are encoded into utf-8 character set. Otherwise, the counter will not count the access properly.
Then, simply using URL class, we create an URL object and open a steam:
URL statsUrl = new URL(cntURL);
statsUrl.openStream();
That is it! There is no need to research what parameters are in http header. It is simply a matter of forming a proper string to which to open a connection.
I have written a simple method that retrieves all info required for the request and have inserted a call to it in a method where I download the file from a server.

Java file download code design problem

I have a Java project which is used as a component in a webapp. This java code writes an xls file in a specific folder. I want to provide a download functionality for this file which should be triggered as soon as file writing is done.
The problem is - without a server environment, how can write a download functionality?
Don't write to file in a specific folder. Just write to the HTTP response body immediately. The downloading job should just be done in the webapp's code. I assume that you're using Servlets. If you set the HTTP response Content-Disposition header to attachment, then the browser will pop a Save as dialogue. If you also set the Content-Type header, then the browser will understand what to do with it (e.g. it will then be able to ask Do you want to open it in Excel or to save? and so on).
response.setHeader("Content-Type", "application/vnd.ms-excel");
response.setHeader("Content-Disposition", "attachment;filename=\"" + filename + "\"");
// Now write xls to response.getOutputStream() instead of FileOutputStream.
If the API of that Java project is well designed, then you should have a method something like this:
public void writeXls(OutputStream output) throws IOException {
// Do your job to write xls to output. E.g. if you were using POI HSSF:
// WritableWorkbook workBook = Workbook.createWorkbook(output);
// ...
}
This way you can call it in the servlet as follows after setting the aforementioned headers:
yourClass.writeXls(response.getOutputStream());
Even more, it could easily be reused/tested in a plain vanilla Java application like follows:
yourClass.writeXls(new FileOutputStream("/path/to/foo.xls"));
This is how i do it. I show a download sql in my page.
response.setHeader("Content-Disposition", "attachment; " +
"filename=ContactPurge.sql");
response.setContentType("application/x-sql-data");
response.getWriter().write(procsql);
response.getWriter().write(sql);
response.flushBuffer();

open/save file in smartGWT

I have implemented RPCService, RPCServiceAsync & RPCServieImpl. On clicking a button a service in server side will be called and it will fetch data from DB and file is created. Once the file is created, then i need to open that file in client side and need to prompt a dialog box with open/save options.
how can i implement this opening a file part. pls suggest a way to implement t.. Reply pls.. thanks in advance....
#Hambend : I still have one more clarification !.. how to call this doGet method in another servlet i.e. in my onmodule load class i am having lot of widgets in seperate layout and one such a widget is BUTTON ? onclicking this button service RPCServiceImpl is called and all manipulations are done and file is created in a serperate function (public int GenerateFile(String name)() ) . how to make that function to call doGet method ? since doGet needs request,response parameters to be passed along with it?? pls suggest me a method to call that method. thanks in advance
GWT's RPC services are only able to send java objects back to the client. To send a file back to the user you'll need to use a non-GWT java servlet. Here's some code I've used before for serving up jpeg images from a repository.
public class ImageServlet extends HttpServlet {
private final String repository = "/var/images/";
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException {
String filename = request.getParameter("file");
// Security: '..' in the filename will let sneaky users access files
// not in your repository.
filename = filename.replace("..", "");
File file = new File(repository + filename);
if (!file.exists())
throw new FileNotFoundException(file.getAbsolutePath());
response.setHeader("Content-Type", "image/jpeg");
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-disposition", "attachment;filename=\"" + filename + "\"");
BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
BufferedOutputStream bos = new BufferedOutputStream(response.getOutputStream());
byte[] buf = new byte[1024];
while (true) {
int length = bis.read(buf);
if (length == -1)
break;
bos.write(buf, 0, length);
}
bos.flush();
bos.close();
bis.close();
}
}
"Content-disposition: attachment" should cause most browsers to download the file instead of displaying it, with the filename defaulting to whatever you provide. The way you would use this servlet is to have the user call the RPCService that you already have, which saves the file to the repository folder. Then, you link or redirect them to this servlet with a url such as http://your.domain.com/fileServlet?file=myFile.jpg. Obviously with this setup you have a security risk where users can download other people's files if they can guess the filenames.
What you might like to do is merge the database code from your RPC service into this servlet. There's no need to save the file anywhere on the server, you can take your database results and write them into response.getOutputStream() or response.getWriter() in exactly the same way you would write them to file, except that the result goes straight to the user. As long as you set your content headers correctly the user won't notice the difference.
You can't call this method from another servlet, the only way to make a browser to download it as a file is to access it through a normal HTTP request. First you declare the servlet in your web.xml file like you would a GWT RPC service:
<servlet>
<servlet-name>ImageServlet</servlet-name>
<servlet-class>
com.package.ImageServlet
</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ImageServlet</servlet-name>
<url-pattern>/imageServlet</url-pattern>
</servlet-mapping>
Now any HTTP GET requests going to http://your.tomcat.server/webapp/imageServlet will get picked up by ImageServlet.doGet(). Then on the client side you can either make a normal html link to the file:
new HTML("<a href='" + GWT.getHostPageBaseURL() + "imageServlet?file=" + filename + "'>download</a>");
...or, you should be able to put this in a ClickHandler (I haven't tested it):
Window.Location.assign(GWT.getHostPageBaseURL() + "imageServlet?file=" + filename);
If the file is text, then you always back back an Object with an array of Strings.
If binary then simply a byte[] in the class would do.

Categories

Resources