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
Related
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
I am returning an object as json through the existing rest service, however I wish to save the json to the users local disk.
You can write the file in the server. And use the following code to send the file to user.
String path = context.getSession().getServletContext().getRealPath("/") + "path to file";
InputStream inputStream = prepairFileStream(response, path);
if (inputStream == null) return;
FileCopyUtils.copy(inputStream, response.getOutputStream());
Only the user can choose to save a file on their local disk.
You can advise a browser (provided that a browser is involved on the user's side) to prompt the user with a "Save As..." dialog by including a Content-Disposition header with your response:
Content-Disposition: attachment; filename="fname.json"
(List of HTTP header fields)
You can do something like this:-
testFunction: function(req, res){
var yourJson = {"test":"testing"};
var text={"filename.txt":yourJson};
res.set({'Content-Disposition': 'attachment;filename=\"cards.txt\"','Content-type': 'text/plain'});
res.send(text['filename.txt']);
}
this will download your json data as a file in your downloads folder.
I'm trying to export a report to Excel. Using POI I'm able to store in to the path (say D:/reports) which I hardcoded in my code.
My requirement is, before the report generation, to ask for the path, the user wants to save the report to. How to achieve this?
You cannot store a file in user's computer without his permission/action.
1)Store your generated file in container (Tomcat's folder).
2)Write the file as response content.
3) Users get's a prompt to select the location to save the file to disk.
4) Delete the generated file after successfully writing to the user's computer.
you can't store the file in users computer.
Convert your workbook to byte array and write the file as response content.
Try the following:
// converting workbook to byte array
ByteArrayOutputStream outStream = new ByteArrayOutputStream();
byte[] bytes = null;
try {
workbook.write(outStream);
bytes = outStream.toByteArray();
} finally {
outStream.close();
}
// setting file properties
response.setContentType('application/vnd.ms-excel');
response.setHeader("Content-disposition", "attachment;filename=excelname.xls");
// writing the byte[] to repsonse.
OutputStream out = response.getOutputStream();
out.write(bytes);
out.close();
By using the above code, you don't need save the file in tomcat and User gets a prompt to save the file in his location.
Hello i am making a servlet that gets the image from a
Everything in my servlet works fine. The only problem is that i want to know what is the name of the uploaded image so that i can store its full path in a database. How to i so that?
This is the code that upload the file but, it doesn't provide me the actual name of the original image. f.getName gives me the name of my tag.
Part f= request.getPart("imgCoverInserisci");
InputStream imageInputStream = f.getInputStream();
System.out.println("Path where image will be saved: "+request.getContextPath()+"/Immagini/");
/*returns null*/ String nomeFile=request.getParameter("imgCoverInserisci");
f.getName(); //return name of input tag
FileOutputStream out = new FileOutputStream ("C:\\Users\\Salvatore\\Documents\\NetBeansProjects\\TestFumettopoli\\web\\Immagini\\copertineFumetti\\"+nomeFile);
// write bytes taken from uploaded file to target file
int ch = imageInputStream.read();
while (ch != -1) {
out.write(ch);
ch = imageInputStream.read();
}
out.close();
imageInputStream.close();
I solved this problem in a different way. I used javascript to parse the name of the file image everytime the Onchange event occured. The javascript function then assigned the name of the file in a hidden input tag. Later the servlet only needed to read this as a parameter and the trick is done!
the javascript code is here
I know this is a little broad, but here's the situation:
I am using JSP and Java. I have a file located on my server. I would like to add a link to the screen that, when clicked, would open the file for the user to view. The file can either appear in a window in the web browser, or pop up the program needed to open the file (similar to when you are outputting with iText to the screen, where Adobe opens to display the file). I know my output stream already, but how can I write the file to the output stream? Most of what I have read has only dealt with text files, but I might be dealing with image files, etc., as well.
Any help is appreciated!
Thanks!
You need to add certain fields to the response. For a text/csv, you'd do:
response.setContentType("text/csv"); // set MIME type
response.setHeader("Content-Disposition", "attachment; filename=\"" strExportFileName "\"");
Here's a forum on sun about it.
Here's a simple implementation on how to achieve it:
protected void doPost(final HttpServletRequest request,
final HttpServletResponse response) throws ServletException,
IOException {
// extract filename from request
// TODO use a whitelist to avoid [path-traversing][1]
File file = new File(getFileName(request));
InputStream input = new FileInputStream(file);
response.setContentLength((int) file.length());
// TODO map your file to the appropriate MIME
response.setContentType(getMimeType(file));
OutputStream output = response.getOutputStream();
byte[] bytes = new byte[BUFFER_LENGTH];
int read = 0;
while (read != -1) {
read = input.read(bytes, 0, BUFFER_LENGTH);
if (read != -1) {
output.write(bytes, 0, read);
output.flush();
}
}
input.close();
output.close();
}
You need to create a 'download' servlet which writes the file to the response output stream with correct mime types. You can not reliably do this from within a .jsp file.
We usually do it with a 'download servlet' which we set the servletmapping to /downloads, then append path info to identify the asset to serve. The servlet verifies the request is valid, sets the mime header then delivers the file to the output stream. It's straightforward, but keep the J2EE javadocs handy while doing it.