I want to allow end-users of my site to download files from the server,
I tried to use the classic method using 2 jsp files :
index.jsp :
download the file
download.jsp :
<%
String filename = "file.xls";
String filepath = "C:\\Files\\";
response.setContentType("APPLICATION/OCTET-STREAM");
response.setHeader("Content-Disposition","attachment; filename=\"" + filename + "\"");
java.io.FileInputStream fileInputStream=new java.io.FileInputStream(filepath + filename);
int i;
while ((i=fileInputStream.read()) != -1) {
out.write(i);
}
fileInputStream.close();
%>
But, it's not working with 2 Page Template in Fatwire 7.6.2,
Is that because I am not allowed to use reponse object in Fatwire ?
Using response object within a Sites (aka "fatwire") jsp is indeed discouraged. The typical way to make files available for download in Sites is to model the data in an asset, then use blobserver tags to render a url. See http://docs.oracle.com/cd/E29542_01/apirefs.1111/e39371/JSP/render-getbloburl.html for examples and other similar tags.
If you don't want to put these files into assets, then you may be better off not using blobserver tags and simply making them available directly through the webserver.
Phil
Related
I have the following code for opening a local web page with a parameter:
String url = "file:///C:/work/my_page.html?";
String params = "message=HelloWorld";
Desktop.getDesktop().browse(new URI(url + params));
But, when the browser is opened, the parameters string (?message=HelloWorld) is removed.
While when I call some page with http:// prefix, it does work.
How can I make it work also with local file ? (i.e. such that starts with file:///)
You cannot.
http:// is one protocol which allows parameters.
file:// is another protocol which does not allow parameters.
Suggestion is - create local web site (for example jetty) and use http potocol only. BTW, all other http stuff like AJAX will not work either.
I found a workaround that solves it. It abuses the fact that from the browser, it's possible to redirect to another page with parameters, even though the target page is local.
Instead of calling the URL directly from Java, do the following:
Create a temporary HTML file. Into this temporary file print an HTML code that will automatically redirect the browser to the real URL you want to open. Example:
<meta http-equiv="refresh" content="0; url=file:///C:/work/my_page.html?message=helloWorld" />
Then, just launch the browser on the temp HTML file, which will immediately redirect you to the real URL :)
Here is the Java code for doing it in one line:
String url = "file:///C:/work/my_page.html?";
String params = "message=HelloWorld";
Desktop.getDesktop().browse(new URI(createHtmlLauncher(url + params)));
The method createHtmlLauncher():
private String createHtmlLauncher(String targetUrl) throws Exception {
String launcherFile = System.getProperty("java.io.tmpdir") + "local_launcher.html";
File launcherTempFile = new File(launcherFile);
PrintWriter writer = null;
try {
writer = new PrintWriter(launcherTempFile, "UTF-8");
} catch (Exception e) {
throw new Exception("Error opening file for writing: " + launcherTempFile.getAbsolutePath() + " : " + e.getMessage());
}
writer.println("<meta http-equiv=\"refresh\" content=\"0; url=" + targetUrl + "\" />");
writer.close();
return "file:///" + launcherFile.replace("\\", "/");
}
Note that for avoiding filling the disk with a lot of temp files, this code uses the same file for redirection each time. It means that if you open a few pages without any delay, you'll probably have race problems.
The solution is to use a generated temp file instead. The disadvantage of it is that you can't know when to remove these files from the disk. If you don't delete them and you have some extreme usage of the feature, the disk can get full.
here i'm trying to read pdf file from server using java servlet. the below code i'm getting file path if file exists and then try to read file but,file does not open ?
String filePath = dirName;
String fileName = si + "_" + dnldFilename;
FileInputStream fileToDownload = new FileInputStream(filePath.concat(fileName);
response.setContentType("application/pdf");
response.setHeader("Content-Disposition", "attachment; filename=" + fileName);
response.setContentLength(fileToDownload.available());
int c;
while ((c = fileToDownload.read()) != -1) {
response.getOutputStream().write(c);
}
response.getOutputStream().flush();
response.getOutputStream().close();
fileToDownload.close();
The bug is here:
response.setContentLength(fileToDownload.available());
The InputStream#available() doesn't do what you (and the average Java starter) think. It doesn't return the total content length which is what the response header represents. It returns the amount of bytes available for reading without blocking all other threads (i.e. bytes which are currently already put in hardware buffer). If this is lower than the actual file size, then the client may simply stop reading the remainder of the response. In other words, the client got only a part of the PDF file, because you told the client that the desired part is of exactly the given length.
You need to construct a normal java.io.File and get the file size via File#length().
Here's a complete rewrite, reducing further legacy Java IO boilerplate too. This assumes you're on at least Java 7 (as Java 6 is EOL since 2013, no one would expect you're 2 years after date still at Java 6 anyway):
File file = new File(filePath, fileName);
response.setHeader("Content-Type", getServletContext().getMimeType(file.getName()));
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "attachment; filename=\"" + file.getName() + "\"");
Files.copy(file.toPath(), response.getOutputStream());
That's it. Do note that the above code snippet is this way reusable for all other kinds of files too. You can manage unknown content types via <mime-mapping> entries in web.xml.
Also note that I'm converting the content length to string as the setContentLength() takes only an int and File#length() returns long, which would fail if the file is larger than 2GB. In case you're on Servlet 3.1 (Tomcat 8, etc) already, make use of new setContentLengthLong() method.
response.setContentLengthLong(file.length());
See also:
Simplest way to serve static data from outside the application server in a Java web application
Abstract template for static resource servlet
I have a jsp written in which i am downloading certain files... they are pdf, zip, ppt and wmv. All the file types works except wmv. I couldnt figure out problem. When i play wmv file i get following error.
Windows Media Player cannot play the file. The Player might not support the file type or might not support the codec that was used to compress the file.
In my jps i have written code as following
response.setContentType("video/x-ms-wmv");
response.setCharacterEncoding("utf-8");
response.setHeader("Content-disposition", "attachment; filename=123.wmv;");
String fileName = "/logs/164266828.wmv";
FileInputStream input = new FileInputStream(fileName);
BufferedInputStream buf = new BufferedInputStream(input);
int readBytes = 0;
ServletOutputStream myOut = response.getOutputStream( );
while((readBytes = buf.read( )) != -1)
myOut.write(readBytes);
Any inputs or modifications would be of great help !!!
Do not use JSP to stream binary data. JSP may have corrupted it with template text (whitespace and so on outside those <% %> things). Move this code to the doGet() method of a servlet class and invoke the servlet instead of JSP.
Unrelated to the concrete problem, those files seems static files. You don't necessarily need a servlet for this if you have full control over your server. In case of for example Tomcat, you could add the folder with the static files as another <Context> to the server.xml file.
See also:
Reliable data serving
Simplest way to serve static data from outside the application server in a Java web application
I am working on an application wherein I have to download a PPT file using a JSP page. I am using the following code, but it's not working.
<% try {
String filename = "file/abc.ppt";
// set the http content type to "APPLICATION/OCTET-STREAM
response.setContentType("APPLICATION/OCTET-STREAM");
// initialize the http content-disposition header to
// indicate a file attachment with the default filename
// "myFile.txt"
String disHeader = "Attachment Filename=\"abc.ppt\"";
response.setHeader("Content-Disposition", disHeader);
// transfer the file byte-by-byte to the response object
File fileToDownload = new File(filename);
FileInputStream fileInputStream = new
FileInputStream(fileToDownload);
int i;
while ((i=fileInputStream.read())!=-1)
{
out.write(i);
}
fileInputStream.close();
out.close();
}catch(Exception e) // file IO errors
{
e.printStackTrace();
}
%>
Can anybody solve this problem?
Not only the Content-Disposition header is incorrect, but you're incorrectly using JSP instead of a Servlet for this particular task.
JSP is a view technology. Everything outside the scriptlets <% %> will be printed to the response, including whitespace characters such as newlines. It would surely corrupt binary files.
You could trim the whitespace in the JSP file, but scriptlets are discouraged since a decade and nowadays considered bad practice. Raw Java code belongs in Java classes, not in JSP files. The real solution is to use a HttpServlet for this.
Create a class which extends HttpServlet, implement the doGet() method, move the Java code from the JSP file into this method, map this servlet on a certain url-pattern and your problem should disappear. You can find here a basic example of such a servlet.
Off the top there should be a semicolon in the Content-Disposition header ("attachment*;* filename ...)
You should also probably do a response.reset() before starting to set headers and stream. Internet Explorer has really strange rules about streaming files from secure sockets and won't work right if you don't clear the caching headers.
I am developing an application using JSF in Eclipse IDE with Derby as database. I have a feature to upload files to the database. But the file name is getting stored as "C:\Documents and Settings\Angeline\Desktop\test.txt" instead of "test.txt". How do I get to store only "test.txt" as file name in the database?
This is my code in JSF:
File to Upload:
<t:inputFileUpload id="fileupload" value="#{employeeBean.upFile}" storage="file"/>
Java Bean Code:
String fileName=upFile.getName();
The value of this fileName=C:\Documents and Settings\Angeline\Desktop\test.txt.
lastSlashIndex = name.lastIndexOf("\\");
if (lastSlashIndex == -1) {
lastSlashIndex = name.lastIndexOf("/"); //unix client
}
String shortName = name;
if (lastSlashIndex != -1) {
shortName = name.substring(lastSlashIndex);
}
Note that if the filename on *nix contain a \ this won't work.
new java.io.File(myPath).getName();
You could probably do something more efficient with only String operations but depending on the application load and other operations, it might not be worth it.
Tomahawk t:inputFileUpload is built on top of Apache Commons FileUpload and Apache Commons IO. In the FileUpload FAQ you can find an entry titled "Why does FileItem.getName() return the whole path, and not just the file name? " which contains the following answer:
Internet Explorer provides the entire path to the uploaded file and not just the base file name. Since FileUpload provides exactly what was supplied by the client (browser), you may want to remove this path information in your application. You can do that using the following method from Commons IO (which you already have, since it is used by FileUpload).
String fileName = item.getName();
if (fileName != null) {
filename = FilenameUtils.getName(filename);
}
In short, just use FilenameUtils#getName() to get rid of the complete path which has been unnecessarily appended by MSIE (all the other real/normal webbrowsers doesn't add the complete client side path, but just provide the sole filename as per the HTML forms specs).
So, all you basically need to do is replacing
String fileName = upFile.getName();
by
String fileName = FilenameUtils.getName(upFile.getName());
I think it would be safer to see this not as a string manipulation problem, but as a path name parsing problem:
String filename = new File(pathname).getName()