Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

FileUpload with JAX-RS

I try to do file upload from a JavaScript client to a JAX-RS Java server.

I use the following REST upload function on my server:

@POST @Produces('application/json') UploadDto upload(         @Context HttpServletRequest request,         @QueryParam("cookie") String cookie) {      def contentType     byte [] fileBytes      log.debug "upload - cookie: "+cookie      try{         if (request instanceof MultipartHttpServletRequest) {             log.debug "request instanceof MultipartHttpServletRequest"              MultipartHttpServletRequest myrequest = request             CommonsMultipartFile file = (CommonsMultipartFile) myrequest.getFile('file')             fileBytes = file.bytes             contentType = file.contentType             log.debug ">>>>> upload size of the file in byte: "+ file.size         }         else if (request instanceof SecurityContextHolderAwareRequestWrapper) {             log.debug "request instanceof SecurityContextHolderAwareRequestWrapper"              SecurityContextHolderAwareRequestWrapper myrequest = request              //get uploaded file's inputStream             InputStream inputStream = myrequest.inputStream              fileBytes = IOUtils.toByteArray(inputStream);             contentType = myrequest.getHeader("Content-Type")             log.debug ">>>>> upload size of the file in byte: "+ fileBytes.size()         }         else {             log.error "request is not a MultipartHttpServletRequest or SecurityContextHolderAwareRequestWrapper"             println "request: "+request.class         }     }     catch (IOException e) {         log.error("upload() failed to save file error: ", e)     } } 

On the client side I send the file as follows:

var str2ab_blobreader = function(str, callback) {     var blob;     BlobBuilder = window.MozBlobBuilder || window.WebKitBlobBuilder             || window.BlobBuilder;     if (typeof (BlobBuilder) !== 'undefined') {         var bb = new BlobBuilder();         bb.append(str);         blob = bb.getBlob();     } else {         blob = new Blob([ str ]);     }     var f = new FileReader();     f.onload = function(e) {         callback(e.target.result)     }     f.readAsArrayBuffer(blob); }  var fileName = "fileName.jpg"; var contentType = "image/jpeg"; if (file.type.toString().toLowerCase().indexOf("png") > -1) {     fileName = "fileName.png";     contentType = "image/png"; }  var xhrNativeObject = new XMLHttpRequest(); var urlParams = ?test=123; xhrNativeObject.open("post", url + urlParams, true); xhrNativeObject.setRequestHeader("Content-Type", contentType);  xhrNativeObject.onload = function(event) {      var targetResponse = event.currentTarget;     if ((targetResponse.readyState == 4)             && (targetResponse.status == 200)) {         var obj = JSON.parse(targetResponse.responseText);         console.log(obj.uploadImageId);     } else {         console.log("fail");     } }  var buffer = str2ab_blobreader(file, function(buf) {     xhrNativeObject.send(buf); }); 

When I use the code in my Grails Controller it worked well but when I use it in a REST Resource I always get: request is not a MultipartHttpServletRequest or SecurityContextHolderAwareRequestWrapper

The log output is

request: com.sun.proxy.$Proxy58 

The send a file blob from JavaScript I use XMLHttpRequest which contains the blob in the body and some query parameters.

How can I make JAX-RS file upload working? How do I receive some additional query params with my POST request?

like image 900
confile Avatar asked Sep 11 '14 22:09

confile


People also ask

What is the purpose of using JAX-RS?

JAX-RS is a Java programming language API designed to make it easy to develop applications that use the REST architecture. The JAX-RS API uses Java programming language annotations to simplify the development of RESTful web services.

What are the implementations of JAX-RS?

JAX-RS is a standard defined in Java Specification Request 311 (JSR-311) and Jersey / RESTEasy are implementations of it.


2 Answers

On Server Side you can use something like this

@POST @Path("/fileupload")  //Your Path or URL to call this service @Consumes(MediaType.MULTIPART_FORM_DATA) public Response uploadFile(         @DefaultValue("true") @FormDataParam("enabled") boolean enabled,         @FormDataParam("file") InputStream uploadedInputStream,         @FormDataParam("file") FormDataContentDisposition fileDetail) {      //Your local disk path where you want to store the file     String uploadedFileLocation = "D://uploadedFiles/" + fileDetail.getFileName();     System.out.println(uploadedFileLocation);     // save it     File  objFile=new File(uploadedFileLocation);     if(objFile.exists())     {         objFile.delete();      }      saveToFile(uploadedInputStream, uploadedFileLocation);      String output = "File uploaded via Jersey based RESTFul Webservice to: " + uploadedFileLocation;      return Response.status(200).entity(output).build();  } private void saveToFile(InputStream uploadedInputStream,         String uploadedFileLocation) {      try {         OutputStream out = null;         int read = 0;         byte[] bytes = new byte[1024];          out = new FileOutputStream(new File(uploadedFileLocation));         while ((read = uploadedInputStream.read(bytes)) != -1) {             out.write(bytes, 0, read);         }         out.flush();         out.close();     } catch (IOException e) {          e.printStackTrace();     }  } 

Again this can be checked with the client code in java with

public class TryFile { public static void main(String[] ar)        throws HttpException, IOException, URISyntaxException {     TryFile t = new TryFile();     t.method(); } public void method() throws HttpException, IOException, URISyntaxException {     String url = "http://localhost:8080/...../fileupload";  //Your service URL     String fileName = ""; //file name to be uploaded     HttpClient httpclient = new DefaultHttpClient();     HttpPost httppost = new HttpPost(url);     FileBody fileContent = new FiSystem.out.println("hello");     StringBody comment = new StringBody("Filename: " + fileName);     MultipartEntity reqEntity = new MultipartEntity();     reqEntity.addPart("file", fileContent);     httppost.setEntity(reqEntity);      HttpResponse response = httpclient.execute(httppost);     HttpEntity resEntity = response.getEntity(); } } 

With HTML, you can simply check with this code

<html> <body> <h1>Upload File with RESTFul WebService</h1> <form action="<Your service URL (htp://localhost:8080/.../fileupload)" method="post" enctype="multipart/form-data">    <p>     Choose a file : <input type="file" name="file" />    </p>    <input type="submit" value="Upload" /> </form> 

To get QueryParam, Check @QueryParam or for header param use @HeaderParam

Example of @QueryParam

Example of @HeaderParam

Try this, hope this helps you with your problem.

like image 115
ajitksharma Avatar answered Sep 28 '22 17:09

ajitksharma


There is no Jax-RS way to do this. Each server have their own extensions, all using Multi-part form submissions. For example, in CXF, the following will allow you to upload via a multipart form. (Attachment is a CXF specific extension)

@Consumes(MediaType.MULTIPART_FORM_DATA) public Response uploadFile(@Multipart(value = "vendor") String vendor,         @Multipart(value = "uploadedFile") Attachment attr) { 

whereas the following is the same for Jersey (FormDataParam is a Jersey extension):

 @Consumes(MediaType.MULTIPART_FORM_DATA_TYPE)  public String postForm(          @DefaultValue("true") @FormDataParam("enabled") boolean enabled,          @FormDataParam("data") FileData bean,          @FormDataParam("file") InputStream file,          @FormDataParam("file") FormDataContentDisposition fileDisposition) { 

(I've ignored the @Path, @POST and @Produces, and other non-relevant annotations.)

like image 41
Jeff Wang Avatar answered Sep 28 '22 15:09

Jeff Wang