OK - I suspect it is something to do with a VOID method instead of returning
a type...
How do I overcome this if I wish to serve via HttpServletResponse?
On Fri, Apr 24, 2009 at 10:09 AM, James Allchin <james_at_knowledgemill.com>wrote:
> Hi All,
>
> Thanks to everyone who keeps answering my questions on the forum. The
> support is excellent.
>
> My current question is how to serve binary content i.e. a file out through
> my RESTful services.
>
> I have managed to accept a file through my REST implementation with the
> following method (it uses apache.commons upload) which is a nice combo in my
> view (particularly streaming capabilities).
>
> @POST
> @Path("user/{userId}/artifacts/{artifactId}/content")
> @Consumes("multipart/form-data")
> //_at_Consumes("multipart/mixed")
> public void setArtifactBinaryContent(@PathParam("userId") long userId
> , @PathParam("artifactId") long
> artifactId
> , @javax.ws.rs.core.Context
> HttpServletRequest request)
> throws Exception {
> // First write the file to disk
> FileItemFactory factory = new DiskFileItemFactory();
> ServletFileUpload upload = new ServletFileUpload(factory);
> List items = null;
> try {
> items = upload.parseRequest(request);
> Iterator iter = items.iterator();
> while (iter.hasNext()) {
> FileItem item = (FileItem)iter.next();
> if (!item.isFormField()) {
> File fileLocator = new File("/fileshare/filedata/"
> + artifactId + ".dat");
> item.write(fileLocator);
> }
> }
> // Assuming success we now update the link and set to
> enabled
> dA.updateArtifactLink(0, userId, artifactId,
> "/fileshare/filedata/" + artifactId + ".dat");
> dA.updateArtifactEnabled(0, userId, artifactId, true);
> }
> catch (Exception e) {
> e.printStackTrace();
> }
>
> }
>
> This works a treat... The problem I am having is now serving the file. I am
> trying the following:
>
> @GET
> @Path("user/{userId}/artifacts/{artifactId}/content")
> @Produces("application/octet-stream")
> public void getArtifactBinaryContent(@PathParam("userId") long userId
> , @PathParam("artifactId") long
> artifactId
> , @javax.ws.rs.core.Context
> HttpServletResponse response)
> throws Exception {
> try {
> // Get an internal representation of an artifact
> InternalArtifact ia = dA.getInternalArtifact(0, userId,
> artifactId);
>
> // Get the file from disk
> File f = new File(ia.getLink());
> int fLength = (int)f.length();
>
> // Set the response header header
> response.setContentType("application/octet-stream");
> response.setContentLength(fLength);
> response.setHeader( "Content-Disposition", "attachment;
> filename=\"" + artifactId + "\"" );
> ServletOutputStream sos = response.getOutputStream();
>
> // Output the file stream
> byte[] bbuf = new byte[100];
> DataInputStream in = new DataInputStream(new
> FileInputStream(f));
> int length = 0;
> while ((in != null) && ((length = in.read(bbuf)) != -1))
> {
> sos.write(bbuf,0,length);
> }
> in.close();
> sos.flush();
> sos.close();
> }
> catch (Exception e) {
> e.printStackTrace();
> }
> }
>
> When deploying it moans with the following error:
>
> SEVERE: Servlet /ACMERest threw load() exception
> com.sun.jersey.api.container.ContainerException: Method, public void
> com.acme.rest.MainService.getArtifactBinaryContent(long,long,javax.servlet.http.HttpServletResponse)
> throws java.lang.Exception, annotated with GET of resource, class
> com.acme.rest.MainService, is not recognized as valid Java method annotated
> with @HttpMethod.
>
> Does anyone know what the issue is here. Is it incorrect to be using
> @Context to access the HttpServletResponse object?
>
> Is there another way to serve a file perhaps?
>
> Thanks,
>
> James
>
>
>