Java から Cloud Storage を使う

Java 用の Bookshelf のチュートリアルのこのパートでは、画像を Google Cloud Storage に格納する方法を説明します。

このページは複数ページからなるチュートリアルの一部です。説明の最初から設定手順を確認するには、Java Bookshelf アプリに移動してください。

Cloud Storage バケットの作成

Cloud Storage バケットを作成する手順は次のとおりです。バケットは、Cloud Storage でデータを格納する基本的なコンテナです。

バケットを作成するには:

  1. ターミナル ウィンドウで次のコマンドを実行します。

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

  2. バケットのデフォルト ACL を public-read に設定します。これによりユーザーは、自身がアップロードした画像を見られるようになります。

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

設定の構成

ローカルマシンでのアプリの実行

アプリをローカルで実行するには:

  1. getting-started-java/bookshelf/3-binary-data ディレクトリで次のコマンドを入力してローカル ウェブサーバーを起動します。

    mvn -Plocal clean jetty:run-exploded -DprojectID=[YOUR-PROJECT-ID]
  2. ウェブブラウザで http://localhost:8080 に移動します。

これで、アプリのウェブページを閲覧できるようになります。また、表紙画像を付けて書籍を追加し、追加した書籍を編集したり削除したりすることもできます。

App Engine フレキシブル環境へのアプリのデプロイ

  1. 次のコマンドを入力してアプリをデプロイします。

    mvn appengine:deploy -DprojectID=YOUR-PROJECT-ID
    
  2. ウェブブラウザで、次のアドレスを入力します。[YOUR_PROJECT_ID] は実際のプロジェクト ID で置き換えます。

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

アプリを更新する場合は、最初にデプロイしたときと同じコマンドを使って、更新バージョンをデプロイできます。デプロイを行うと、アプリの新しいバージョンが作成され、それがデフォルトのバージョンに設定されます。古いバージョンはそのまま残り、関連付けられた VM インスタンスも同様に残ります。すべてのアプリ バージョンと VM インスタンスが課金対象のリソースとなるのでご注意ください。

アプリのデフォルト以外のバージョンを削除することで、コストを削減できます。

アプリのバージョンを削除する手順は次のとおりです。

  1. GCP Console の [App Engine のバージョン] ページに移動します。

    [バージョン] ページに移動

  2. 削除したい、デフォルト以外のアプリのバージョンの横にあるチェックボックスをクリックします。
  3. ページ上部にある [削除] ボタンをクリックし、アプリのバージョンを削除します。

課金対象のリソースをクリーンアップする方法の詳細については、このチュートリアルの最後のステップにあるクリーンアップ セクションを参照してください。

アプリケーションの構造

バイナリデータの構造の例

ここではバイナリデータ(この例では画像)の格納場所として Cloud Storage が使われます。さらに書籍情報の格納場所としても Cloud Datastore が使われます。

コードを理解する

このセクションでは、アプリケーションのコードとその動作を順を追って説明します。

ユーザーのアップロードに対応する

Google Cloud Storage API for Java の使い方は簡単です。ほとんどの場合、ローカルな認証は 1 行で記述できます。

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

blob を Cloud Storage にアップロードする

getPart を使用して POST リクエストからファイルを読み取ります。アップロードする前に、そのファイルが要件を満たしていることを確認してください。

/**
 * 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;
}

次に、タイムスタンプを付加してファイル名を一意にします。storage.create で、bucketName および fileName を指定して作成した BlobInfo を受け渡し、さらにアクセス制御リストを設定することで、全ユーザーが当該ファイルの InputStream を読み込んで受け渡すことができるようにします。これによりオブジェクトの公開 URL が得られます。

/**
 * 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();
}
このページは役立ちましたか?評価をお願いいたします。