Using Cloud Storage with Java for the App Engine standard environment

This part of the Bookshelf tutorial for Java shows how to store images in Cloud Storage.

This page is part of a multi-page tutorial. To start from the beginning and read the setup instructions, go to Java Bookshelf app.

Creating a Cloud Storage bucket

The following instructions show how to create a Cloud Storage bucket. Buckets are the basic containers that hold your data in Cloud Storage.

  1. In a terminal window, enter the following command:

    gsutil mb gs://[YOUR-BUCKET-NAME]

    Where:

    • [YOUR-BUCKET-NAME] represents the name of your Cloud Storage bucket.
  2. To view uploaded images in the bookshelf app, set the bucket's default access control list (ACL) to public-read.

    gsutil defacl set public-read gs://[YOUR-BUCKET-NAME]

    Running the app on your local machine

    To run the app locally:

    1. In the getting-started-java/bookshelf-standard/3-binary-data directory, enter the following command to start a local web server:

      mvn -Plocal clean appengine:devserver -Dbookshelf.bucket=[YOUR-BUCKET]
      Replace [YOUR-BUCKET] with your bucket name.
    2. In your web browser, go to http://localhost:8080.

    Now you can browse the app's web pages, add books with cover images, edit books, and delete books.

    Deploying the app to the App Engine standard environment

    To deploy to the App Engine standard environment:

    1. To create a Cloud Datastore index that is uploaded to the Bookshelf app, create at least one book, and then click My Books. Note, building the app using the clean command deletes that local index so do this on the build of the app that you are going to deploy.
    2. In the getting-started-java/bookshelf-standard/3-binary-data directory, enter this command to deploy the app:
      mvn appengine:update -Dappengine.appId=[YOUR-PROJECT-ID] -Dappengine.version=[YOUR-VERSION] -Dbookshelf.bucket=[YOUR-BUCKET].appspot.com
      Replace [YOUR-PROJECT-ID] with your project ID and [YOUR-VERSION] with your version, for example, 1, or 2, or some other string value you want to use.
    3. In your web browser, enter the following address:
      https://[YOUR-PROJECT-ID].appspot.com
      Replace [YOUR-PROJECT-ID] with your project ID.

    After you update your app, you can redeploy the updated version by entering the same command as when you first deployed the app as well as specifying the same project ID and version. This overwrites the currently deployed app. If you specify a different version string in the updated command line, the new deployment creates a new version of your app and promotes it to be the currently serving version.

    You can reduce costs by deleting the non-serving versions of your app.

    To delete an app version:

    1. In the GCP Console, go to the Versions page for App Engine.

      Go to the Versions page

    2. Select the checkbox for the non-default app version you want to delete.
    3. Click Delete to delete the app version.

    For complete information about cleaning up billable resources, see the Cleaning up section in the final step of this tutorial.

    App structure

    Binary data sample structure

    The app uses Cloud Storage to store binary data, such as pictures in this case. The app continues to use Cloud Datastore for book information.

    Understanding the code

    This section walks you through the app's code and explains how it works.

    Handle user uploads

    It is simple to use the Cloud Storage API for Java. In most cases, a single line is all you need to authenticate locally.

    static {
      storage = StorageOptions.getDefaultInstance().getService();
    }

    Upload blobs to Cloud Storage

    Verify the file matches your requirements before uploading it.

    
    /**
     * Checks that the file extension is supported.
     */
    private void checkFileExtension(String fileName) throws ServletException {
      if (fileName != null && !fileName.isEmpty() && fileName.contains(".")) {
        String[] allowedExt = {".jpg", ".jpeg", ".png", ".gif"};
        for (String ext : allowedExt) {
          if (fileName.endsWith(ext)) {
            return;
          }
        }
        throw new ServletException("file must be an image");
      }
    }

    Make the filename unique by appending a timestamp to it. Using storage.create, pass a BlobInfo created with bucketName and fileName, and set the access control list so that all users can read and pass the file's InputStream. The result is the public URL for the object.

    /**
     * Uploads a file to Google Cloud Storage to the bucket specified in the BUCKET_NAME
     * environment variable, appending a timestamp to end of the uploaded filename.
     */
    @SuppressWarnings("deprecation")
    public String uploadFile(FileItemStream fileStream, final String bucketName)
        throws IOException, ServletException {
      checkFileExtension(fileStream.getName());
    
      DateTimeFormatter dtf = DateTimeFormat.forPattern("-YYYY-MM-dd-HHmmssSSS");
      DateTime dt = DateTime.now(DateTimeZone.UTC);
      String dtString = dt.toString(dtf);
      final String fileName = fileStream.getName() + dtString;
    
      // the inputstream is closed by default, so we don't need to close it here
      BlobInfo blobInfo =
          storage.create(
              BlobInfo
                  .newBuilder(bucketName, fileName)
                  // Modify access list to allow all users with link to read file
                  .setAcl(new ArrayList<>(Arrays.asList(Acl.of(User.ofAllUsers(), Role.READER))))
                  .build(),
              fileStream.openStream());
      // return the public download link
      return blobInfo.getMediaLink();
    }
Was this page helpful? Let us know how we did:

Send feedback about...