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?
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.
JAX-RS is a standard defined in Java Specification Request 311 (JSR-311) and Jersey / RESTEasy are implementations of it.
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.
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.)
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With