Uploading JSON and binary file in one request - java

I am looking to create a RESTful API for use with an Android and iOS app. So far I have been experimenting with using Jersey on the server and then the appropriate http libraries on the client side. At the moment I have been using multipart/related as the mimetype for the request with JSON forming the first part of the body then a jpeg image as the second.
So far I have had problems with making the request to the server, getting a 406 Not Acceptable from Jersey. I note that multipart/related is primarily used in sending emails. Is there actually a way that I can support mixed type content as an upload or have I entirely mis-understood the usage of multipart/related in this context?

You may want to look at this blog, for more information, but here is the important part to help you along:
http://www.mkyong.com/webservices/jax-rs/file-upload-example-in-jersey/
#POST
#Path("/upload")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(
#FormDataParam("file") InputStream uploadedInputStream,
#FormDataParam("file") FormDataContentDisposition fileDetail) {
String uploadedFileLocation = "d://uploaded/" + fileDetail.getFileName();
// save it
writeToFile(uploadedInputStream, uploadedFileLocation);
String output = "File uploaded to : " + uploadedFileLocation;
return Response.status(200).entity(output).build();
}
I expect you want multipart/form-data instead, as this is part of the description of multipart/related:
The Multipart/Related media type is intended for compound objects
consisting of several inter-related body parts. For a
Multipart/Related object, proper display cannot be achieved by
individually displaying the constituent body parts. The content-type
of the Multipart/Related object is specified by the type parameter.
The "start" parameter, if given, points, via a content-ID, to the
body part that contains the object root. The default root is the
first body part within the Multipart/Related body.
For more on this mime type you can look at
https://www.rfc-editor.org/rfc/rfc2387

If you are wanting to submit image along with the json body, you can base64 encode the image and include the base64 string in the json. Then on the server side, you base64 decode the string and upload the image file to the blobstore. See the file upload example (at the bottom of the page) here https://developers.google.com/appengine/docs/java/blobstore/overview
Alternatively, you could do a separate upload to the blobstore and get the blobkey for the uploaded image. You can then include the blobkey in the json body that you post to the server.Using this approach you would need to get the uploadurl every time you need to do a new image upload.

Related

Which one is better for Creating an JAVA Springboot Rest Endpoint to upload file - Multipart file vs base 64 encoded byte array in the POST body

I am trying to create an application, where documents are uploaded from the Angular application and send to the Spring Rest Endpoint, which will save the document in Database. I could see two options
Creating an endpoint which accepts base encoded array of bytes in the body of the POST request.
Creating the endpoint to accept Multipart file
Which one is better in terms of performance and why ? Please note, my document size can be from a couple of MBs to 25 MB.
Base64 is a way to encode binary data into an ASCII character format by translating it into a radix-64 representation.
I recommend you that never use Base64 for large file/data upload to the server because it converts whole data and posts it to the server.
An the other hand, Multipart is a way to upload the file to a server in the form of parts which are in bytes. Multipart/form-data is applied to a form though, so you can send everything in a multi-part form, including "regular" data also.
So, I think this can be useful for you:
#PostMapping("/api/update")
public ResponseEntity upload(#NotNull #NotEmpty #RequestParam("file") MultipartFile file) {}

Java Jax-rs - get only file body in payload - remove headers

I have to upload a binary file to my server using UI/Postman client. My backend code for Rest API is:
#POST
#Produces({JSONHeaders.MEDIA_TYPE_JSONAPI, MediaType.APPLICATION_JSON})
#Path("loadLicense")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response loadLicense2(#ApiParam("load a license") File input) {
....
}
But the file I get has header details added to it which I don't need. File content is something like:
----------------------------013134317098674079511595^M
Content-Disposition: form-data; name="file"; filename="license.lic"^M
Content-Type: application/octet-stream^M
^M
^#^#^T.^#^#m.....^#^#^#^K^#^A^#^#^#^#^C^#^#^#(^#.^E^#^#^#^K^#.^#^#^#^G.^#^#^#^K^#.^#^#^#^#^B^#^#^#^K^#.^#^#^#^#^#^#^#^#^K^#.^#^#^#^#^F^#^#^#^K^#.^#^#^
^#^#^#^U^#^N^BGR^#^#^#^#^M^#^G^Bc^#^#^#^#^K^#^O^B1.0^#^#^#^#^Q^#4^Bpermanent^#^#^#^#^G^#.
^G.^V......I..^HC_.^^.^U...Y..G.^K.R.^?^O&..^.{V.Z.......h^B.<^O....w'#bk.^B]..*...8.W93...Z.\..... ..g.a+.....,^M
----------------------------013134317098674079511595--^M
But I just need the binary content. Is there any way to do that?
Note: I tried #FormParam - it doesn't work and I get this error
The #FormParam is utilized when the content type of the request entity is not application/x-www-form-urlencoded]
Tried #FormDataParam - not able to resolve it in code.
Instead of #FormParam you might need to use #FormDataParam, depending on how you send the data via Postman. They have different purposes, i.e. are for use with different MIME types:
#FormParam is intended to be used with MIME type application/x-www-form-urlencoded (constant MediaType.APPLICATION_FORM_URLENCODED)
#FormDataParam is intended to be used with multipart/form-data (constant MediaType.MULTIPART_FORM_DATA)
The following snippet expects the file being sent via form data:
#POST
#Produces({JSONHeaders.MEDIA_TYPE_JSONAPI, MediaType.APPLICATION_JSON})
#Path("loadLicense")
#Consumes(MediaType.MULTIPART_FORM_DATA)
public Response loadLicense2(
#FormDataParam("file") InputStream istream,
#FormDataParam("file") FormDataContentDisposition disp) {
}
The input stream contains the binary data, the second parameter gives you some information about the uploaded file, e.g. the file name.
You need the jersey-media-multipart artifact for this:
https://mvnrepository.com/artifact/org.glassfish.jersey.media/jersey-media-multipart
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
<version>3.0.2</version>
</dependency>

Returning file/files in JSON response (Java-Jersey-ReST)

I am working on a use case where I am displaying user's messages on a JSP. Details of the flow are:
All the messages will be shown in a table with icon for attachments
When the user clicks on attachment, the file should get downloaded.
If there is more than one attachment, user can select the required
one to download.
The attachments will be stored on the local filesystem and the path for the attachments will be determined by the system.
I have tried to implement by referring to these SO questions:
Input and Output binary streams using JERSEY?
Return a file using Java Jersey
file downloading in restful web services
However, it's not solving my purpose. I have the following questions:
Is it possible to send message data (like subject, message, message id, etc) along with the attachments (Inputstream) in one response?
If yes, what needs to be the MediaType for #Produces annotation in my resource method? Currently my resource is annotated with #Produces(MediaType.APPLICATION_JSON). Will this work?
How to send the file data in the response?
Any pointers appreciated. TIA.
You can add custom data to the response Header, so yes you are able to send such message data. Add the data to the response Header.
#Produces(MediaType.APPLICATION_JSON) will not work, unless the clients will accept JSON as a file, what they should and will not do ;)
The correct MediaType depends on what kind of file you want to submit.
You can use the default MediaType / MIME-Type MediaType.APPLICATION_OCTET_STREAM / application/octet-stream (Is there a “default”
MIME type?) but I think it's better to use the correct and exact MIME-Type for your file.
You will find working examples for sending file data with jersey in Input and Output binary streams using JERSEY? - so there is no need to answer this again :)
Hope this was helpful somehow, have a nice day.

Send image using http

I've got the following setup. I have to send an image over http to a browser or other device. The tricky thing about the whole it is, that I have very limited control over the http-packet creation.
I only can provide the content type field and the message body as a string.
Is there a way how I could create an http-packet containing a image with this limited configuration facilities?
You need to have:
Content-Type as 'application/image'
data in body as binary
With your limitation as you can have only strings in body, an image cannot be sent in response.
You could convert your image to a base64 string: http://www.base64-image.de/

Posting contents of a file using HttpClient?

I want to send the contents of a file as part of a http request using Apache HttpClient and I could not figure out how to pass on the file contents in the request body.
You didn't specify the format....
Most likely, you want to send a POST request, the contents will be multipart/form-data MIME type. This emulates what a browser sends from an <INPUT type="file" ...> form element. This requires some pretty sophisticated parsing on the server side to extract the multiple parts from the body and correctly extract the file data from the other fields (if any). Fortunately, commons-fileupload does this perfectly. The first answer regarding FilePart is exactly right.
Alternatively, you could simply post the raw contents of a file as the body of the request by using an InputStreamRequestEntity. This may be much simpler if you're writing your own server side to receive the data. The server side is as simple as streaming the request's InputStream to disk. I use this technique for uploads with Google Gears.
Check out FilePart and related.
Here's the sample.

Categories