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.
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 have a Java web application running on Tomcat. I want to load static images that will be shown both on the Web UI and in PDF files generated by the application. Also new images will be added and saved by uploading via the Web UI.
It's not a problem to do this by having the static data stored within the web container but storing and loading them from outside the web container is giving me headache.
I'd prefer not to use a separate web server like Apache for serving the static data at this point. I also don't like the idea of storing the images in binary in a database.
I've seen some suggestions like having the image directory being a symbolic link pointing to a directory outside the web container, but will this approach work both on Windows and *nix environments?
Some suggest writing a filter or a servlet for handling the image serving but those suggestions have been very vague and high-level without pointers to more detailed information on how to accomplish this.
I've seen some suggestions like having the image directory being a symbolic link pointing to a directory outside the web container, but will this approach work both on Windows and *nix environments?
If you adhere the *nix filesystem path rules (i.e. you use exclusively forward slashes as in /path/to/files), then it will work on Windows as well without the need to fiddle around with ugly File.separator string-concatenations. It would however only be scanned on the same working disk as from where this command is been invoked. So if Tomcat is for example installed on C: then the /path/to/files would actually point to C:\path\to\files.
If the files are all located outside the webapp, and you want to have Tomcat's DefaultServlet to handle them, then all you basically need to do in Tomcat is to add the following Context element to /conf/server.xml inside <Host> tag:
<Context docBase="/path/to/files" path="/files" />
This way they'll be accessible through http://example.com/files/.... For Tomcat-based servers such as JBoss EAP 6.x or older, the approach is basically the same, see also here. GlassFish/Payara configuration example can be found here and WildFly configuration example can be found here.
If you want to have control over reading/writing files yourself, then you need to create a Servlet for this which basically just gets an InputStream of the file in flavor of for example FileInputStream and writes it to the OutputStream of the HttpServletResponse.
On the response, you should set the Content-Type header so that the client knows which application to associate with the provided file. And, you should set the Content-Length header so that the client can calculate the download progress, otherwise it will be unknown. And, you should set the Content-Disposition header to attachment if you want a Save As dialog, otherwise the client will attempt to display it inline. Finally just write the file content to the response output stream.
Here's a basic example of such a servlet:
#WebServlet("/files/*")
public class FileServlet extends HttpServlet {
#Override
protected void doGet(HttpServletRequest request, HttpServletResponse response)
throws ServletException, IOException
{
String filename = URLDecoder.decode(request.getPathInfo().substring(1), "UTF-8");
File file = new File("/path/to/files", filename);
response.setHeader("Content-Type", getServletContext().getMimeType(filename));
response.setHeader("Content-Length", String.valueOf(file.length()));
response.setHeader("Content-Disposition", "inline; filename=\"" + file.getName() + "\"");
Files.copy(file.toPath(), response.getOutputStream());
}
}
When mapped on an url-pattern of for example /files/*, then you can call it by http://example.com/files/image.png. This way you can have more control over the requests than the DefaultServlet does, such as providing a default image (i.e. if (!file.exists()) file = new File("/path/to/files", "404.gif") or so). Also using the request.getPathInfo() is preferred above request.getParameter() because it is more SEO friendly and otherwise IE won't pick the correct filename during Save As.
You can reuse the same logic for serving files from database. Simply replace new FileInputStream() by ResultSet#getInputStream().
See also:
Recommended way to save uploaded files in a servlet application
Abstract template for a static resource servlet (supporting HTTP cache)
How to retrieve and display images from a database in a JSP page?
How to stream audio/video files such as MP3, MP4, AVI, etc using a Servlet
You can do it by putting your images on a fixed path (for example: /var/images, or c:\images), add a setting in your application settings (represented in my example by the Settings.class), and load them like that, in a HttpServlet of yours:
String filename = Settings.getValue("images.path") + request.getParameter("imageName")
FileInputStream fis = new FileInputStream(filename);
int b = 0;
while ((b = fis.read()) != -1) {
response.getOutputStream().write(b);
}
Or if you want to manipulate the image:
String filename = Settings.getValue("images.path") + request.getParameter("imageName")
File imageFile = new File(filename);
BufferedImage image = ImageIO.read(imageFile);
ImageIO.write(image, "image/png", response.getOutputStream());
then the html code would be <img src="imageServlet?imageName=myimage.png" />
Of course you should think of serving different content types - "image/jpeg", for example based on the file extension. Also you should provide some caching.
In addition you could use this servlet for quality rescaling of your images, by providing width and height parameters as arguments, and using image.getScaledInstance(w, h, Image.SCALE_SMOOTH), considering performance, of course.
Requirement : Accessing the static Resources (images/videos., etc.,) from outside of WEBROOT directory or from local disk
Step 1 :
Create a folder under webapps of tomcat server., let us say the folder name is myproj
Step 2 : Under myproj create a WEB-INF folder under this create a simple web.xml
code under web.xml
<web-app>
</web-app>
Directory Structure for the above two steps
c:\programfile\apachesoftwarefoundation\tomcat\...\webapps
|
|---myproj
| |
| |---WEB-INF
| |
|---web.xml
Step 3:
Now create a xml file with name myproj.xml under the following location
c:\programfile\apachesoftwarefoundation\tomcat\conf\catalina\localhost
CODE in myproj.xml:
<Context path="/myproj/images" docBase="e:/myproj/" crossContext="false" debug="0" reloadable="true" privileged="true" />
Step 4:
4 A) Now create a folder with name myproj in E drive of your hard disk and create a new
folder with name images and place some images in images folder (e:myproj\images\)
Let us suppose myfoto.jpg is placed under e:\myproj\images\myfoto.jpg
4 B) Now create a folder with name WEB-INF in e:\myproj\WEB-INF and create a web.xml in WEB-INF folder
Code in web.xml
<web-app>
</web-app>
Step 5: Now create a .html document with name index.html and place under e:\myproj
CODE under index.html
Welcome to Myproj
The Directory Structure for the above Step 4 and Step 5 is as follows
E:\myproj
|--index.html
|
|--images
| |----myfoto.jpg
|
|--WEB-INF
| |--web.xml
Step 6: Now start the apache tomcat server
Step 7: open the browser and type the url as follows
http://localhost:8080/myproj
then u display the content which is provided in index.html
Step 8: To Access the Images under your local hard disk (outside of webroot)
http://localhost:8080/myproj/images/myfoto.jpg
Add to server.xml :
<Context docBase="c:/dirtoshare" path="/dir" />
Enable dir file listing parameter in web.xml :
<init-param>
<param-name>listings</param-name>
<param-value>true</param-value>
</init-param>
This is story from my workplace:
- We try to upload multiply images and document files use Struts 1 and Tomcat 7.x.
- We try to write uploaded files to file system, filename and full path to database records.
- We try to separate file folders outside web app directory. (*)
The below solution is pretty simple, effective for requirement (*):
In file META-INF/context.xml file with the following content:
(Example, my application run at http://localhost:8080/ABC, my application / project named ABC).
(this is also full content of file context.xml)
<?xml version="1.0" encoding="UTF-8"?>
<Context path="/ABC" aliases="/images=D:\images,/docs=D:\docs"/>
(works with Tomcat version 7 or later)
Result: We have been created 2 alias. For example, we save images at: D:\images\foo.jpg
and view from link or using image tag:
<img src="http://localhost:8080/ABC/images/foo.jsp" alt="Foo" height="142" width="142">
or
<img src="/images/foo.jsp" alt="Foo" height="142" width="142">
(I use Netbeans 7.x, Netbeans seem auto create file WEB-INF\context.xml)
If you decide to dispatch to FileServlet then you will also need allowLinking="true" in context.xml in order to allow FileServlet to traverse the symlinks.
See http://tomcat.apache.org/tomcat-6.0-doc/config/context.html
If you want to work with JAX-RS (e.g. RESTEasy) try this:
#Path("/pic")
public Response get(#QueryParam("url") final String url) {
String picUrl = URLDecoder.decode(url, "UTF-8");
return Response.ok(sendPicAsStream(picUrl))
.header(HttpHeaders.CONTENT_TYPE, "image/jpg")
.build();
}
private StreamingOutput sendPicAsStream(String picUrl) {
return output -> {
try (InputStream is = (new URL(picUrl)).openStream()) {
ByteStreams.copy(is, output);
}
};
}
using javax.ws.rs.core.Response and com.google.common.io.ByteStreams
if anyone not able to resolve his problem with accepted answer, then note these below considerations:
no need to mention localhost:<port> with <img> src attribute.
make sure you are running this project outside eclipse, because eclipse creates context docBase entry on its own inside its local server.xml file.
Read the InputStream of a file and write it to ServletOutputStream for sending binary data to the client.
Local file You can read a file directly using FileInputStream('path/image.png').
Mongo DataBase file's you can get InputStream using GridFS.
#WebServlet("/files/URLStream")
public class URLStream extends HttpServlet {
private static final long serialVersionUID = 1L;
public URLStream() {
super();
}
protected void service(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException {
File source = new File("D:\\SVN_Commit.PNG");
long start = System.nanoTime();
InputStream image = new FileInputStream(source);
/*String fileID = request.getParameter("id");
System.out.println("Requested File ID : "+fileID);
// Mongo DB GridFS - https://stackoverflow.com/a/33544285/5081877
image = outputImageFile.getInputStream();*/
if( image != null ) {
BufferedInputStream bin = null;
BufferedOutputStream bout = null;
ServletOutputStream sos = response.getOutputStream();
try {
bin = new BufferedInputStream( image );
bout = new BufferedOutputStream( sos );
int ch =0; ;
while((ch=bin.read())!=-1) {
bout.write(ch);
}
} finally {
bin.close();
image.close();
bout.close();
sos.close();
}
} else {
PrintWriter writer = response.getWriter();
writer.append("Something went wrong with your request.");
System.out.println("Image not available.");
}
System.out.println("Time taken by Stream Copy = "+(System.nanoTime()-start));
}
}
Result the URL directly to the src attibute.
<img src='http://172.0.0.1:8080/ServletApp/files/URLStream?id=5a575be200c117cc2500003b' alt="mongodb File"/>
<img src='http://172.0.0.1:8080/ServletApp/files/URLStream' alt="local file"/>
<video controls="controls" src="http://172.0.0.1:8080/ServletApp/files/URLStream"></video>
I did it even simpler. Problem: A CSS file had url links to img folder. Gets 404.
I looked at url, http://tomcatfolder:port/img/blablah.png, which does not exist. But, that is really pointing to the ROOT app in Tomcat.
So I just copied the img folder from my webapp into that ROOT app. Works!
Not recommended for production, of course, but this is for an internal tool dev app.
This question already has an answer here:
Closed 10 years ago.
Possible Duplicate:
how to display a pdf file in jsp using servlet
I retrieve a pdf file from my database and put it in a file like this
String str="select * from files where name='Security.pdf';";
Statement stmt2= conn.createStatement
(ResultSet.TYPE_SCROLL_INSENSITIVE,ResultSet.CONCUR_UPDATABLE);
rs = stmt2.executeQuery(str);
while(rs.next())
{
InputStream input = rs.getBinaryStream("content");
//to create file
File f=new File("c:/pdfile.pdf");
OutputStream out=new FileOutputStream(f);
byte buf[]=new byte[1024];
int len;
while((len=input.read(buf))>0)
out.write(buf,0,len);
out.close();
input.close();
System.out.println("\nFile is created..");
}
Now this is at server end. In my client side, Whenever user clicks a link say
a href=pdf(pdf is my servlet name) in my jsp page, I should display the file retrieved from database on client's Browser.
What should I do?
Set your content-type of the response to pdf
response.setContentType("application/pdf");
Then write the pdf contents into the response object
Don't save the PDF to a file on the server, just send it back to the browser as the servlet's response. Basically, instead of that FileOutputStream, use the OutputStream that you get from calling getOutputStream() on your ServletResponse object. You'll also need to set a Content-Type header so that the browser knows it's a PDF file.
Having a servlet write to a hard-coded path like that is dangerous because several instances of the servlet can run at the same time, in different threads. (Think about what happens if two people enter your servlet's URL in their browsers at the same time.) If they're both writing to the same file at the same time, they'll end up corrupting it.
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.
I have run into an issue in which IE does not open up the Save As/Open dialog box for an Excel document like Firefox does.
So I have created a servlet filter that is using '*.xls' as the url pattern. The issue that I now face (since this is the first filter I have created) is how to get the name of the file that the user wants so that the dialog box gets populated correctly. Currently the filter is invoked when the user selects a link on a given page.
Here is what I came up with:
The above is what I have doFilter().
String fileName = "fileName.xls";
HttpServletRequest httpRequest = (HttpServletRequest) pRequest;
String requestURI = httpRequest.getRequestURI();
if(StringUtils.isNotBlank(requestURI))
{
String uri[] = StringUtils.split(requestURI, '/');
fileName = uri[uri.length - 1];
}
HttpServletResponse httpResponse = (HttpServletResponse) pResponse;
httpResponse.setContentType("application/vnd.ms-excel");
httpResponse.setHeader("Content-disposition", "attachment; filename=\"" + fileName +"\"");
web.xml:
<filter>
<filter-name>ExcelFilter</filter-name>
<filter-class>vsg.rp.common.ExcelFilter</filter-class>
</filter>
<filter-mapping>
<filter-name>ExcelFilter</filter-name>
<url-pattern>*.xls</url-pattern>
</filter-mapping>
This all is working on my development box: Windows XP, JBoss, Eclipse, Oracle. But when it runs on the test server—Linux, Apache/JBoss, Oracle—it does not work. It appears that the filter is not even being called, no errors thrown, etc. Any idea as to why this would happen?
You want the content type set appropriately as well as the content disposition header, thus:
response.setContentType("application/vnd.ms-excel");
response.setHeader("Content-Disposition",
"attachment; filename=\"" + filename +
"\"");
Use the Content-Disposition HTTP header and set it to something like:
attachment; filename=myworkbook.xls
The is a Microsoft Knowledge Base Article all about this problem. And here is an example of setting Content-Disposition in Java code.
In addition to setting the headers for the content type, you'll also want to ensure that the server DOES NOT tell the browser to NOT CACHE the file.
In IE land, if you tell IE not to cache the file, it happily downloads the file... then tries to open the file from the directory it saved the file to... However since the headers said "don't cache" it takes this literally, and doesn't save the file, thus Excel throws an error saying, "There is no file!".
Long story short, tell IE to CACHE the file.