Create Rest Web Service to receive an Image
Solution 1
Example REST Web Service Java Class to Recieve Image
import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.FileOutputStream;
import java.io.IOException;
import java.io.InputStream;
import java.io.OutputStream;
import javax.ws.rs.Consumes;
import javax.ws.rs.FormParam;
import javax.ws.rs.POST;
import javax.ws.rs.Path;
import javax.ws.rs.Produces;
import javax.ws.rs.core.Context;
import javax.ws.rs.core.MediaType;
import javax.ws.rs.core.Response;
import javax.ws.rs.core.UriInfo;
import com.sun.jersey.core.header.FormDataContentDisposition;
import com.sun.jersey.multipart.FormDataParam;
import com.sun.org.apache.xml.internal.security.exceptions.Base64DecodingException;
import com.sun.org.apache.xml.internal.security.utils.Base64;
@Path("/upload")
public class Upload_Documents {
private static final String UPLOAD_FOLDER = "c:/uploadedFiles/";
@Context
private UriInfo context;
/**
* Returns text response to caller containing uploaded file location
*
* @return error response in case of missing parameters an internal
* exception or success response if file has been stored
* successfully
*/
@POST
@Path("/pic")
@Consumes(MediaType.MULTIPART_FORM_DATA)
public Response uploadFile(
@FormDataParam("file") InputStream uploadedInputStream,
@FormDataParam("file") FormDataContentDisposition fileDetail) {
System.out.println("Called Upload Image");
// check if all form parameters are provided
if (uploadedInputStream == null || fileDetail == null)
return Response.status(400).entity("Invalid form data").build();
// create our destination folder, if it not exists
try {
createFolderIfNotExists(UPLOAD_FOLDER);
} catch (SecurityException se) {
return Response.status(500)
.entity("Can not create destination folder on server")
.build();
}
String uploadedFileLocation = UPLOAD_FOLDER + fileDetail.getFileName();
try {
saveToFile(uploadedInputStream, uploadedFileLocation);
} catch (IOException e) {
return Response.status(500).entity("Can not save file").build();
}
return Response.status(200)
.entity("File saved to " + uploadedFileLocation).build();
}
/**
* Utility method to save InputStream data to target location/file
*
* @param inStream
* - InputStream to be saved
* @param target
* - full path to destination file
*/
private void saveToFile(InputStream inStream, String target)
throws IOException {
OutputStream out = null;
int read = 0;
byte[] bytes = new byte[1024];
out = new FileOutputStream(new File(target));
while ((read = inStream.read(bytes)) != -1) {
out.write(bytes, 0, read);
}
out.flush();
out.close();
}
/**
* Creates a folder to desired location if it not already exists
*
* @param dirName
* - full path to the folder
* @throws SecurityException
* - in case you don't have permission to create the folder
*/
private void createFolderIfNotExists(String dirName)
throws SecurityException {
File theDir = new File(dirName);
if (!theDir.exists()) {
theDir.mkdir();
}
}
}
Solution 2
Receiving an InputStream is possible in JAX-RS. You just put the InputStream parameter without annotations:
@POST
public void uploadImage(InputStream stream) {
// store image
}
Pay attention that it will work for any content type.
Although it will work, I would suggest a more "JAX-RS way":
1 Create provider that will create an image class (e.g. java.awt.Image) from the InputStream:
@Provider
@Consumes("image/jpeg")
class ImageProvider implements MessageBodyReader<Image> {
public Image readFrom(Class<Image> type,
Type genericType,
Annotation[] annotations,
MediaType mediaType,
MultivaluedMap<String, String> httpHeaders,
InputStream entityStream) throws IOException,
WebApplicationException {
// create Image from stream
}
}
2 Register the provider the same way you register a resource.
3 Make your resource class to receive Image instead of InputStream.
Why is this approach better?
You separate the deserialization logic from your resource class. So if in the future you would like to support more image formats, you just need to add additional providers, while the resource will stay the same.
c12
Updated on June 12, 2022Comments
-
c12 almost 2 years
How would you design a REST based web service that receives an image file in the form of an
InputStream
? If theInputStream
is posted to a REST end point, how does that end point receive it so that it can create an image file? -
c12 about 13 yearsHi Tarlog, for your first method, how would you send the request to the endpoint? Would the InputStream be a form param? I'm using the google rest client to simulate a request and I don't understand how to test this...
-
Tarlog about 13 years@c12: Sorry, I'm not familiar with Google Rest Client. But it should not be a form param, but a request body. With Wink Client it would be something like: new RestClient().resource(url).post(body), while body is OutputStream.
-
c12 about 13 yearsthanks for the quick reply, I don't think the Rest Client supports it. I will try what you suggested with HTTPClient, maybe that will work..
-
c12 about 13 yearsfor the second solution, is it possible to augment it so it accepts form params as well?
-
c12 about 13 yearssorry for all the questions, but how would you execute the second solution based off the url context? How would a post map to that provider?
-
Tarlog about 13 yearsApache Wink (incubator.apache.org/wink) supports the code I wrote, the benefit using it: you can reuse the JAX-RS providers.
-
Tarlog about 13 yearsYou cannot receive an InputStream as a form-parameter with JAX-RS.
-
Tarlog about 13 years>how would you execute the second solution based off the url context? How would a post map to that provider? - sorry, but I don't understand the question. Provider is used to serialize/deserialize the message body. If you need an access to request information, you can use @Context UriInfo.
-
Sudheer Kumar almost 11 years@Tarlog Can you send me example? Please mail me [email protected]
-
GGO over 6 yearsWe would like to have some explanations
-
Mallikarjuna over 6 yearsThe file is pushed over HTTP POST with encoding type “multipart/form-data” from the client to our web-service. This way you can add multiple parameters to the POST request in addition to the file. Lets start with the requirements. You will need an web/application server like Tomcat, GlassFish or JBoss to deploy the service. In addition we will use jersey framework to build our service endpoint. Please note, GlassFish 4.x version requires jersey version 2 libraries, so if you are using GlassFish 4 use jersey 2.x dependencies. javatutorial.net/java-file-upload-rest-service
-
GGO over 6 yearsYou can edit answer instead ;) sorry it's the moderation
-
sns over 5 yearshow can I do it without Jersey or spring. without any annotation or special framework. I use plain httphandler and maven dependencies.