69

I am looking for the simplest way to upload and store an image (file) to the GAE (java). Googling for hours without any simple and clear result.

Found this link.

But I still don't know how to store an image, and how to retrieve it. I am looking for simple servlet example.

Draken
  • 3,134
  • 13
  • 34
  • 54
OXMO456
  • 3,558
  • 2
  • 25
  • 35

3 Answers3

96

The link your provided "How do I handle file uploads to my app?" explains how you can upload the image.

To host the images, you need to use the Datastore service to store and serve image along with your other data.

Here is a sample code. It is meant as a sketch, for how you can have your own entity (i.g. business, user, etc) have a field for an image. I ignored all error handling and recovery to simplify the code.

Declaring your entity with the image. You can imagine having other fields, e.g. tags, location, etc

@Entity
public class MyImage {
    @PrimaryKey
    @Persistent(valueStrategy = IdGeneratorStrategy.IDENTITY)
    private Long id;

    @Persistent
    private String name;

    @Persistent
    Blob image;

    public MyImage() { }
    public MyImage(String name, Blob image) {
        this.name = name; 
        this.image = image;
    }

    // JPA getters and setters and empty contructor
    // ...
    public Blob getImage()              { return image; }
    public void setImage(Blob image)    { this.image = image; }
}

Then when you start accepting images (watch out for cases where an image with the same name has already been uploaded in addition to the typical file upload failures). ServletFileUpload and IOUtils are classes that are part of the Apache Commons library.

// Your upload handle would look like
public void doPost(HttpServletRequest req, HttpServletResponse res) {
    // Get the image representation
    ServletFileUpload upload = new ServletFileUpload();
    FileItemIterator iter = upload.getItemIterator(req);
    FileItemStream imageItem = iter.next();
    InputStream imgStream = imageItem.openStream();

    // construct our entity objects
    Blob imageBlob = new Blob(IOUtils.toByteArray(imgStream));
    MyImage myImage = new MyImage(imageItem.getName(), imageBlob);

    // persist image
    PersistenceManager pm = PMF.get().getPersistenceManager();
    pm.makePersistent(myImage);
    pm.close();

    // respond to query
    res.setContentType("text/plain");
    res.getOutputStream().write("OK!".getBytes());
}

And finally when you want to serve an image given its name:

Blob imageFor(String name, HttpServletResponse res) {
    // find desired image
    PersistenceManager pm = PMF.get().getPersistenceManager();
    Query query = pm.newQuery("select from MyImage " +
        "where name = nameParam " +
        "parameters String nameParam");
    List<MyImage> results = (List<MyImage>)query.execute(name);
    Blob image = results.iterator().next().getImage();

    // serve the first image
    res.setContentType("image/jpeg");
    res.getOutputStream().write(image.getBytes());
}
Mario Kutlev
  • 4,897
  • 7
  • 44
  • 62
notnoop
  • 58,763
  • 21
  • 123
  • 144
  • wonderful, thank you. can you tell me why byte array will not give proper output, although its getting stored etc., I had posed this question a while ago http://stackoverflow.com/questions/2018597/cannot-fetch-image-data-in-gwt-google-datastore-image-is-strected-out – dhaval Jan 29 '10 at 18:44
  • Eclipse tells me IOUtils isn't supported by GAE... is there a special package or something ? – Julien Feb 20 '11 at 15:06
  • 1
    How to overcome 1 MB restriction – jmj Dec 15 '11 at 06:47
  • 1
    Any 2016 answer on how to do this with Google Cloud Storage which apparently is the recommended way? – Micro Apr 01 '16 at 17:10
10

Use the blobstore API:

The Blobstore API allows your application to serve data objects, called blobs, that are much larger than the size allowed for objects in the Datastore service. Blobs are useful for serving large files, such as video or image files, and for allowing users to upload large data files. Blobs are created by uploading a file through an HTTP request. Typically, your applications will do this by presenting a form with a file upload field to the user. When the form is submitted, the Blobstore creates a blob from the file's contents and returns an opaque reference to the blob, called a blob key, which you can later use to serve the blob. The application can serve the complete blob value in response to a user request, or it can read the value directly using a streaming file-like interface...

gnat
  • 6,213
  • 108
  • 53
  • 73
Claude Vedovini
  • 2,421
  • 21
  • 19
5

Easiest way to use Google App Engine Blob Store serving URL (you save instance time)

import com.google.appengine.api.files.FileService;
import com.google.appengine.api.files.AppEngineFile;
import com.google.appengine.api.files.FileWriteChannel;
import com.google.appengine.api.blobstore.BlobKey;
import com.google.appengine.api.images.ImagesServiceFactory;
import com.google.appengine.api.images.ServingUrlOptions;
...


// your data in byte[] format
byte[] data = image.getData();
/**
 *  MIME Type for
 *  JPG use "image/jpeg" for PNG use "image/png"
 *  PDF use "application/pdf"
 *  see more: https://en.wikipedia.org/wiki/Internet_media_type
 */
String mimeType = "image/jpeg";

// save data to Google App Engine Blobstore 
FileService fileService = FileServiceFactory.getFileService();
AppEngineFile file = fileService.createNewBlobFile(mimeType); 
FileWriteChannel writeChannel = fileService.openWriteChannel(file, true);
writeChannel.write(java.nio.ByteBuffer.wrap(data));
writeChannel.closeFinally();

// your blobKey to your data in Google App Engine BlobStore
BlobKey blobKey = fileService.getBlobKey(file);

// THANKS TO BLOBKEY YOU CAN GET FOR EXAMPLE SERVING URL FOR IMAGES

// Get the image serving URL (in https:// format)
String imageUrl =
  ImagesServiceFactory.getImagesService().getServingUrl(
    ServingUrlOptions.Builder.withBlobKey(blobKey
          ).secureUrl(true));
Dodo
  • 51
  • 1
  • 3
  • I believe that the new way to serve images would be with cloud storage like this: https://cloud.google.com/python/getting-started/using-cloud-storage – Graydyn Young Sep 11 '17 at 20:12