Server
On the server side we develop our web applications in Java using Glassfish for our deployement server. You can have your standard Servlet class that catches your requests, but recently we bumped into Jersey. And I must say, I really love it. Here is for example the code to accept a file upload request.@Path("/file")
public class FileHandler {
@POST
@Path("/upload")
@Consumes("multipart/form-data")
@Produces("text/plain")
public String uploadFile(@FormParam("file") File file, @FormParam("file") FormDataContentDisposition fcdsFile) {
String fileLocation = "/files/" + fcdsFile.getFileName();
File destFile = new File(fileLocation);
// your code here to copy file to destFile
return "1";
}
}That's it. The
FormDataContentDisposition is a recent addition to Jersey which allows you to retrieve the name of the file that is being uploaded.Client
For the client side, I decided to make use of Uploadify. They basically provided a wrapper around SWFUpload using JQuery. Here is the code I used on the client side:<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
<title>SimpleFileUpload</title>
<script type="text/javascript" src="js/swfobject.js"></script>
<script type="text/javascript" src="js/jquery-1.3.2.min.js"></script>
<script type="text/javascript" src="js/jquery.uploadify.v2.1.0.min.js"></script>
<link rel="stylesheet" href="css/uploadify.css" type="text/css" media="screen"/>
<script type="text/javascript">
$(function() {
$('#file_upload').uploadify({
'uploader' : 'swf/uploadify.swf',
'script' : 'rest/file/upload',
'fileDataName' : 'file',
'cancelImg' : 'img/cancel.png',
'multi' : true
});
});
</script>
</head>
<body>
<h1>Simple File Upload</h1>
<h3>Multiple file upload made easy</h3>
<div id="file_upload"></div>
<br/>
<input type="button" value="Clear Queue" onclick="$('#file_upload').uploadifyClearQueue();"/>
<input type="button" value="Submit Queue" onclick="$('#file_upload').uploadifyUpload();"/>
</body>
</html>
Voila, now you have a simple web application that is able to upload files to your server. You can download a sample application here.

14 comments:
Curious would this work with a multi-file upload with Uploadify?
Been looking for some easy-to-implement solutions.
Yes, if you take a look at the code for the client side, you can see that I already used "multi: true". Uploadify will call the method in the FileHandler for each file you upload.
I am having problems in using Uploadify to upload files larger than 100MB as per my requirement.
Can I use Jersey for that as I am currently using apache commons fileupload which breaks for large files. also I am not able to download jersey. is there no download access right now? Can I have the software downloaded from a different location? Any help is appreciated.
Hello Radhika. At the moment it is better to use FormDataParam instead of FormParam when parsing multipart data. And the jersey software should still be available from the same location: Jersey v1.4.
I think you are missing the web.xml sevlet definition...correct? I didn't see how the client will know what backend java app to call, so I added the servlet def to the web.xml and then the following error came back:
javax.servlet.ServletException: Servlet class: 'com.my.test.FileUploaderJersey' does not implement javax.servlet.Servlet
Maybe I am missing something, but would you know why I got that error based on the info I provided above. Note, in your client, you stated that 'rest/file/upload' is the script uploadify is to use. How do you tie that to the back end?
The FileHandler class is not a Servlet, it is actually just a class capable of handling REST calls. The actual endpoint is still a servlet of course, but this servlet is provided by Jersey. If you download my sample application (at the end of the post), you can find the web.xml. In there you will see that the ServletAdaptor is configured to listen to all calls to /rest/*. There is also an init parameter that specifies the package in which Jersey will look for classes that are annotated with @Path.
I tried the example you posted but it did not work. It does not trigger the annotated Java app, I have the web.xml same as your example. Basically, nothing happens on the backend. I commented out everything and just have a print statement to show that the uploadFile method was called, an I only get back "HTTP Error: 404" -- http://en.wikipedia.org/wiki/HTTP_404. I noticed in your example you did not have a button to select the files. Were you able to test this example?
By the way, the last post is by me. I did see you web.xml file, but still not able to get ti working.
- downloaded the sample project
- unzipped it
- opened the project with Netbeans 6.9.1
- resolved a reference problem to the jersey-bundle.jar using jersey-bundle-1.1.5.1.jar
- built the application
- deployed in glassfish: asadmin deploy dist/SimpleFileUpload.war
- pointed browser (firefox) to http://localhost:8080/SimpleFileUpload which showed the following page: screenshot
In other words, for me it worked. Maybe you deploy your the war in a different application server than glassfish?
I did it as your steps, and no error report, but nothing happen.it seems that the path 'rest/file/upload' do not work.
I just type some code like System.out.println("......called") in the method uploadNewFile(,), but when I run the code, submit, no strings in the console.
So... thanks in advance!
Yes I used WebLogic. I like the Jersey technology, but had to do it another way. You Blog was still a good one and thanks for sharing.
Beware: This example doesn't work well with multi-file uploads if you want to actually submit a form after the uploads are completed. Because Uploadify's uploadifyUpload() method is asynchronous, the form tends to submit before the uploads complete.
More importantly, with Jersey 1.5 there's a new method for handling uploads that lets you accept a stream directly. Here's an example handler class, though it'll be nigh-unreadable because of the horrid comment formatting in Blogger, so I'll reproduce it and some more info here:
http://soapyfrogs.blogspot.com/2011/02/handling-file-uploads-with-java-ee-6.html
@Path("/file")
public class FileHandler {
@POST
@Path("/upload")
@Consumes("multipart/form-data")
@Produces("text/plain")
public String uploadFile(
@FormDataParam("file") InputStream file,
@FormDataParam("file") FormDataContentDisposition fileInfo) {
// your code here to copy file to destFile
System.err.println("Received file: " + fileInfo.getFileName() + " as " + file);
return "1";
}
}
Is possible to use JSF context (FacesContext) in Jersey context ? i have tried, but is null. Any idea ? Because i must get a bean from JSF context
"Anonymous": AFAIK, JAX-RS/Jersey doesn't offer any direct access to the JSF context. However, if you're using CDI/Weld then JAX-RS beans share the same session scope, etc, and you can inject JSF beans into a JAX-RS resource class easily.
Alternately, you could store your bean references as session properties on the HttpSession, which you can access via the HttpServletRequest in both JAX-RS and in JSF. In JSF, get it via FacesContext.getExternalContext().In JAX-RS, add a new method parameter to your REST methods: "@Context HttpServletRequest request".
Gee, wouldn't it be nice to have some interface consistency in the Java world! CDI is helping a bit, and Seam Solder should make some more difference once it's stable and supported on all application servers, but for now we get to learn different ways to do different things in different parts of the Java EE stack.
Post a Comment