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?
Add
enctype="multipart/form-data"
in your form submitter code and@Consumes(MediaType.MULTIPART_FORM_DATA_TYPE)
on your @POST method so that we know we are submitting a multipart file and the rest api can consume it. Your rest api method could look likeor
This will create a temporary file on server. It reads from the network and saves into the temporary file.
To program defensively, I would check the content type metadata of the file being uploaded.
Here is what we did to upload file (images in our case) :
Server side
For the client side, we use AngularJS which is coded by another team. I won't be able to explain about it, but here is the code :
And the uploadImage function :
Hope it will help you ...
On Server Side you can use something like this
Again this can be checked with the client code in java with
With HTML, you can simply check with this code
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)
whereas the following is the same for Jersey (FormDataParam is a Jersey extension):
(I've ignored the @Path, @POST and @Produces, and other non-relevant annotations.)