Using Cloud Storage with Java

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]

    Configuring settings

    Running the app on your local machine

    To run the app locally:

    1. In the getting-started-java/bookshelf/3-binary-data directory, enter the following command to start a local web server. Replace [YOUR_PROJECT_ID] with your GCP project ID:

      mvn -Plocal clean jetty:run-exploded -DprojectID=[YOUR-PROJECT-ID]
    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 flexible environment

    1. Deploy the app.

      mvn appengine:deploy -DprojectID=YOUR-PROJECT-ID
      
    2. In your web browser, enter the following address. Replace [YOUR_PROJECT_ID] with your project ID.

      https://[YOUR_PROJECT_ID].appspot-preview.com
      

    When you update your app, you can deploy the updated version using the same command you used when you first deployed the app. The new deployment creates a new version of your app and promotes it to the default version. The older versions of your app remain, as do their associated VM instances. All of these app versions and VM instances are billable resources.

    You can reduce costs by deleting the non-default versions of your app. For complete information about cleaning up billable resources, see the Cleaning up section in the final step of this tutorial.

    App structure

    As illustrated in the following diagram, 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.

    Binary data sample structure

    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

    Read the file from a POST request by using getPart. Verify the file matches your requirements before uploading it.

    /**
     * Extracts the file payload from an HttpServletRequest, checks that the file extension
     * is supported and uploads the file to Google Cloud Storage.
     */
    public String getImageUrl(HttpServletRequest req, HttpServletResponse resp,
                              final String bucket) throws IOException, ServletException {
      Part filePart = req.getPart("file");
      final String fileName = filePart.getSubmittedFileName();
      String imageUrl = req.getParameter("imageUrl");
      // Check extension of file
      if (fileName != null && !fileName.isEmpty() && fileName.contains(".")) {
        final String extension = fileName.substring(fileName.lastIndexOf('.') + 1);
        String[] allowedExt = {"jpg", "jpeg", "png", "gif"};
        for (String s : allowedExt) {
          if (extension.equals(s)) {
            return this.uploadFile(filePart, bucket);
          }
        }
        throw new ServletException("file must be an image");
      }
      return imageUrl;
    }

    Then, 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(Part filePart, final String bucketName) throws IOException {
      DateTimeFormatter dtf = DateTimeFormat.forPattern("-YYYY-MM-dd-HHmmssSSS");
      DateTime dt = DateTime.now(DateTimeZone.UTC);
      String dtString = dt.toString(dtf);
      final String fileName = filePart.getSubmittedFileName() + 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(),
              filePart.getInputStream());
      // return the public download link
      return blobInfo.getMediaLink();
    }
Was this page helpful? Let us know how we did:

Send feedback about...