1. Send the image via json from android device to the server.
2. register your two servlets. One for seving the image to Blob store and one for downloading the image:
<servlet>
<servlet-name>UploadHandlerServlet</servlet-name>
<servlet-class>.servlet.UploadHandlerServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>UploadHandlerServlet</servlet-name>
<url-pattern>/upload</url-pattern>
</servlet-mapping>
<servlet>
<servlet-name>ImagesDownloadServlet</servlet-name>
<servlet-class>.servlet.ImagesDownloadServlet</servlet-class>
</servlet>
<servlet-mapping>
<servlet-name>ImagesDownloadServlet</servlet-name>
<url-pattern>/download</url-pattern>
</servlet-mapping>
and one more servlet that receives the post request with the image. Lets call it "PhoneServlet"
3. From PhoneServlet we are making post request this way:
import java.io.IOException;
import java.io.OutputStream;
import java.io.OutputStreamWriter;
import java.io.PrintWriter;
import java.io.StringReader;
import java.net.HttpURLConnection;
import java.net.MalformedURLException;
import java.net.URL;
private void sendMultipartDataPostReq(byte[] imageByteArray, long boundary, String type) throws MalformedURLException, IOException {
log.warning("sendMultipartDataPostReq( ) START");
String charset = "UTF-8";
String CRLF = "\r\n"; // Line separator required by multipart/form-data.
HttpURLConnection connection = (HttpURLConnection)new URL(getUploadUrl()).openConnection();
connection.setInstanceFollowRedirects(true);
connection.setDoOutput(true);// fires POST request
connection.setRequestMethod("POST");
connection.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
PrintWriter writer = null;
try {
OutputStream output = connection.getOutputStream();
writer = new PrintWriter(new OutputStreamWriter(output, charset), true);// true = autoFlush, important!
// Send normal param issueId
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\""+Constants.PARAMETER_TYPE_ISSUEID+"\"").append(CRLF);
writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF);
writer.append(CRLF);
writer.append(Integer.toString(image.getIssueId())).append(CRLF).flush();
// Send normal param boundary
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\""+Constants.PARAMETER_TYPE_BOUNDARY+"\"").append(CRLF);
writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF);
writer.append(CRLF);
writer.append(Long.toString(boundary)).append(CRLF).flush();
// Send normal param type
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\""+Constants.PARAMETER_TYPE_TYPE+"\"").append(CRLF);
writer.append("Content-Type: text/plain; charset=" + charset).append(CRLF);
writer.append(CRLF);
writer.append(type).append(CRLF).flush();
// Send binary file.
writer.append("--" + boundary).append(CRLF);
writer.append("Content-Disposition: form-data; name=\""+Constants.PARAMETER_TYPE_PHOTO+"\"; filename=\""+ boundary+".jpg" + "\"").append(CRLF);
writer.append("Content-Type: image/jpg").append(CRLF);
writer.append("Content-Transfer-Encoding: binary").append(CRLF);
writer.append(CRLF).flush();
output.write(imageByteArray);
output.flush();// Important! Output cannot be closed. Close of writer will close output as well.
writer.append(CRLF).flush(); // CRLF is important! It indicates end of binary boundary.
writer.append("--" + boundary + "--").append(CRLF);// End of multipart/form-data.
writer.close();
if (connection.getResponseCode() == HttpURLConnection.HTTP_OK) {
log.warning("COnection HTTP_OK");
} else {
log.warning("Server returned HTTP error code");
}
} catch (Exception e) {
log.log(Level.SEVERE, e.toString(), e);
}
log.warning("sendMultipartDataPostReq( ) END");
}
4. This invokes UploadServlet
public class UploadHandlerServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
private static Logger log = Logger.getLogger(UploadHandlerServlet.class.getName());
@Override
public void doPost(HttpServletRequest req, HttpServletResponse res) throws IOException {
log.warning("UploadHandlerServlet doPost START");
BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
Map<String, List<BlobKey>> blobs = blobstoreService.getUploads(req);
List<BlobKey> keys = blobs.get(Constants.PARAMETER_TYPE_PHOTO);
String issueId = req.getParameter(Constants.PARAMETER_TYPE_ISSUEID);
String type = req.getParameter(Constants.PARAMETER_TYPE_TYPE);
String boundary = req.getParameter(Constants.PARAMETER_TYPE_BOUNDARY);
EntityManager em = EMF.get().createEntityManager();
if (type!=null && type.equals(Constants.IMAGE_TYPE_IMAGE)) {
log.warning("UploadHandlerServlet doPost: IMAGE_TYPE_IMAGE");
Issue issue = em.find(Issue.class, Integer.parseInt(issueId));
//we expect only one image so we get only the first key
Image image = new Image(issue,keys.get(0).getKeyString(),true, Long.parseLong(boundary));
em.getTransaction().begin();
em.persist(image);
em.getTransaction().commit();
log.warning("UploadHandlerServlet doPost new Image key is saved");
}
else if (type!=null && type.equals(Constants.IMAGE_TYPE_THUMBNAIL)) {
log.warning("UploadHandlerServlet doPost: IMAGE_TYPE_THUMBNAIL");
Image image = ImageDAO.getImageByTimeCreated(Long.parseLong(boundary));
if (image !=null) {
image.setBlobKeyThumbnail(keys.get(0).getKeyString());
em.getTransaction().begin();
em.merge(image);
em.getTransaction().commit();
}
log.warning("UploadHandlerServlet doPost new Thumbnail key is saved");
}
log.warning("UploadHandlerServlet doPost END");
}
}
and after UploadHandlerServlet our pictures are in the database as blob keys and in the google BlobStore.
5. We can download them using the ImagesDownloadServlet:
public class ImagesDownloadServlet extends HttpServlet {
private static final long serialVersionUID = 1L;
@Override
public void doGet(HttpServletRequest req, HttpServletResponse res) throws IOException {
String blobkeyString = req.getParameter("blobkey");
if (blobkeyString != null) {
BlobKey blobKey = new BlobKey(blobkeyString);
BlobstoreService blobstoreService = BlobstoreServiceFactory.getBlobstoreService();
blobstoreService.serve(blobKey, res);
}
else {
res.sendError(400, "One or more parameters are not set");
}
}
}
6. The important thing for making the POST request is to use java.net library and nothing else from apache for example to make POST request. All these servlets are on our server.