Cloud Storage 사용

Cloud Storage를 사용하여 영화, 이미지, 기타 정적 콘텐츠 등의 파일을 저장하고 제공할 수 있습니다.

이 문서에서는 앱에서 Cloud Storage용 Cloud 클라이언트 라이브러리를 사용하여 Python 버전 3.7 이하 및 버전 3.8 이상 버전용 Cloud Storage

시작하기 전에

  • 개발 환경 설정의 안내에 따라 환경과 프로젝트를 설정하고 App Engine에서 앱이 구조화되는 방식을 이해합니다. 이 문서에 설명된 샘플 애플리케이션을 실행할 때 필요하므로 프로젝트 ID를 기록해 둡니다.
  • 다음 명령어를 호출하여 애플리케이션용 Cloud Storage 버킷을 만듭니다.

    gsutil mb gs://[YOUR_BUCKET_NAME]
    
  • 공개 읽기 가능 버킷으로 만들어 파일을 제공할 수 있도록 합니다.

    gsutil defacl set public-read gs://[YOUR_BUCKET_NAME]
    

샘플 다운로드

Go

저장소를 복제하려면 다음을 사용하세요.

v1.18 이상

  git clone https://github.com/GoogleCloudPlatform/golang-samples.git
  cd golang-samples/appengine_flexible/storage

v1.15 이하

  git clone https://github.com/GoogleCloudPlatform/golang-samples.git
  cd golang-samples/appengine_flexible/go115_and_earlier/storage

Java

저장소를 복제하려면 다음을 사용하세요.

버전 11/17

  git clone https://github.com/GoogleCloudPlatform/java-docs-samples
  cd java-docs-samples/flexible/java-11/cloudstorage

버전 8

  git clone https://github.com/GoogleCloudPlatform/java-docs-samples
  cd java-docs-samples/flexible/java-8/cloudstorage

Node.js

저장소를 복제하려면 다음을 사용하세요.

v18 이상

  git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples/
  cd nodejs-docs-samples/appengine/storage/flexible

v16 이하

  git clone https://github.com/GoogleCloudPlatform/nodejs-docs-samples/
  cd nodejs-docs-samples/appengine/storage/flexible_nodejs16_and_earlier

PHP

저장소를 복제하려면 다음을 사용하세요.

git clone https://github.com/GoogleCloudPlatform/php-docs-samples
cd php-docs-samples/appengine/flexible/storage

Python

저장소를 복제하려면 다음을 사용하세요.

v3.8 이상

git clone https://github.com/GoogleCloudPlatform/python-docs-samples
cd python-docs-samples/appengine/flexible/storage

v3.7 및 이전

git clone https://github.com/GoogleCloudPlatform/python-docs-samples
cd python-docs-samples/appengine/flexible_python37_and_earlier/storage

Ruby

저장소를 복제하려면 다음을 사용하세요.

버전 3.2

git clone https://github.com/GoogleCloudPlatform/ruby-docs-samples
cd ruby-docs-samples/appengine/flexible/storage/

버전 3.1 이하

git clone https://github.com/GoogleCloudPlatform/ruby-docs-samples
cd ruby-docs-samples/appengine/flexible/ruby31-and-earlier/storage/

.NET

  1. 샘플 앱을 다운로드하고 압축을 풉니다.

  2. 명령줄을 사용하는 경우 다음 앱 디렉터리로 이동합니다.

    버전 6 이상

    dotnet-docs-samples\appengine\flexible\CloudStorage\CloudStorage.Sample

    버전 3.1 이하

    flex-dotnet3-and-earlier 브랜치를 사용합니다.

      dotnet-docs-samples\appengine\flexible\CloudStorage
    

    애플리케이션을 로컬에서 실행하려면 서비스 계정을 설정하고 사용자 인증 정보를 다운로드합니다.

  3. Google Cloud 콘솔에서 사용자 인증 정보 목록을 엽니다.

    사용자 인증 정보 목록 열기

  4. 사용자 인증 정보 만들기를 클릭합니다.

  5. 서비스 계정 키를 선택합니다.

    서비스 계정 키 만들기 창이 열립니다.

  6. 서비스 계정 아래의 드롭다운 상자를 클릭한 후 Compute Engine 기본 서비스 계정을 클릭합니다.

  7. 키 유형JSON을 선택하세요.

  8. 만들기를 클릭합니다.

    새 비공개 키 창이 표시되고 비공개 키가 자동으로 다운로드됩니다.

  9. 닫기를 클릭합니다.

프로젝트 구성 수정 및 종속 항목 설치

Go

app.yaml에서 GCLOUD_STORAGE_BUCKET을 설정합니다. 이 값은 이전에 만든 Cloud Storage 버킷의 이름입니다.

v1.18 이상

# Copyright 2019 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

runtime: go
env: flex

runtime_config:
  operating_system: ubuntu22
  runtime_version: 1.19

automatic_scaling:
  min_num_instances: 1

env_variables:
  GCLOUD_STORAGE_BUCKET: your-bucket-name

v1.15 이하

# Copyright 2023 Google LLC
#
# Licensed under the Apache License, Version 2.0 (the "License");
# you may not use this file except in compliance with the License.
# You may obtain a copy of the License at
#
#     https://www.apache.org/licenses/LICENSE-2.0
#
# Unless required by applicable law or agreed to in writing, software
# distributed under the License is distributed on an "AS IS" BASIS,
# WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
# See the License for the specific language governing permissions and
# limitations under the License.

runtime: go
env: flex

automatic_scaling:
  min_num_instances: 1

env_variables:
  GCLOUD_STORAGE_BUCKET: your-bucket-name

Java

app.yaml에서 이전에 BUCKET_NAME을 프로젝트용으로 만든 Cloud Storage로 설정합니다.

버전 11/17

runtime: java
env: flex
runtime_config:
  operating_system: ubuntu18
  runtime_version: 11
handlers:
- url: /.*
  script: this field is required, but ignored

env_variables:
  BUCKET_NAME: YOUR-BUCKET-NAME

버전 8

#  Copyright 2023 Google Inc.
#
#  Licensed under the Apache License, Version 2.0 (the "License");
#  you may not use this file except in compliance with the License.
#  You may obtain a copy of the License at
#
#       http://www.apache.org/licenses/LICENSE-2.0
#
#  Unless required by applicable law or agreed to in writing, software
#  distributed under the License is distributed on an "AS IS" BASIS,
#  WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
#  See the License for the specific language governing permissions and
#  limitations under the License.

runtime: java
env: flex

handlers:
- url: /.*
  script: this field is required, but ignored

env_variables:
  BUCKET_NAME: YOUR-BUCKET-NAME

pom.xml에서 com.google.cloud를 종속 항목으로 설정하고 google-cloud-storage를 해당 종속 항목의 artifactID로 지정합니다. 이 종속 항목은 Cloud Storage를 사용하기 위한 함수를 제공합니다.

버전 11/17

<!--  Using libraries-bom to manage versions.
See https://github.com/GoogleCloudPlatform/cloud-opensource-java/wiki/The-Google-Cloud-Platform-Libraries-BOM -->
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>libraries-bom</artifactId>
      <version>26.32.0</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
    <dependency>
      <groupId>org.springframework.boot</groupId>
      <artifactId>spring-boot-dependencies</artifactId>
      <version>${spring.boot.version}</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependencies>
  <dependency>
    <groupId>com.google.cloud</groupId>
    <artifactId>google-cloud-storage</artifactId>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-web</artifactId>
  </dependency>
  <dependency>
    <groupId>javax.servlet</groupId>
    <artifactId>javax.servlet-api</artifactId>
    <type>jar</type>
    <scope>provided</scope>
  </dependency>
  <dependency>
    <groupId>org.junit.vintage</groupId>
    <artifactId>junit-vintage-engine</artifactId>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.junit-pioneer</groupId>
    <artifactId>junit-pioneer</artifactId>
    <version>2.2.0</version>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-inline</artifactId>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.mockito</groupId>
    <artifactId>mockito-junit-jupiter</artifactId>
    <scope>test</scope>
  </dependency>
  <dependency>
    <groupId>org.springframework.boot</groupId>
    <artifactId>spring-boot-starter-test</artifactId>
    <scope>test</scope>
  </dependency>

</dependencies>

버전 8

<!--  Using libraries-bom to manage versions.
See https://github.com/GoogleCloudPlatform/cloud-opensource-java/wiki/The-Google-Cloud-Platform-Libraries-BOM -->
<dependencyManagement>
  <dependencies>
    <dependency>
      <groupId>com.google.cloud</groupId>
      <artifactId>libraries-bom</artifactId>
      <version>26.28.0</version>
      <type>pom</type>
      <scope>import</scope>
    </dependency>
  </dependencies>
</dependencyManagement>

<dependencies>
  <dependency>
    <groupId>com.google.cloud</groupId>
    <artifactId>google-cloud-storage</artifactId>
  </dependency>
</dependencies>

Node.js

app.yaml에서 프로젝트 ID를 GOOGLE_CLOUD_PROJECT 환경 값에 추가합니다. 그런 다음 GCLOUD_STORAGE_BUCKET 환경 값을 이전에 만든 Cloud Storage 버킷의 이름으로 설정합니다.

v18 이상

runtime: nodejs
env: flex
runtime_config:
  operating_system: ubuntu22

env_variables:
  GCLOUD_STORAGE_BUCKET: YOUR_BUCKET_NAME

v16 이하

runtime: nodejs
env: flex

env_variables:
  GCLOUD_STORAGE_BUCKET: YOUR_BUCKET_NAME

package.json에서 @google-cloud/storage를 종속 항목으로 추가합니다. 이 종속 항목은 Cloud Storage를 사용하기 위한 기능을 제공합니다.

v18 이상

{
  "name": "appengine-storage",
  "description": "Node.js Google Cloud Storage sample for Google App Engine",
  "scripts": {
    "start": "node app.js",
    "test": "c8 mocha -p -j 2 system-test/*.test.js --exit --timeout=30000"
  },
  "engines": {
    "node": ">=16.0.0"
  },
  "dependencies": {
    "@google-cloud/storage": "^7.0.0",
    "express": "^4.18.2",
    "multer": "^1.4.5-lts.1",
    "pug": "^3.0.2"
  },
  "devDependencies": {
    "@types/express": "^4.17.17",
    "@types/multer": "^1.4.7",
    "@types/proxyquire": "^1.3.28",
    "@types/supertest": "^2.0.12",
    "@types/uuid": "^9.0.1",
    "c8": "^8.0.0",
    "mocha": "^10.2.0",
    "proxyquire": "^2.1.3",
    "supertest": "^6.3.3",
    "uuid": "^9.0.0"
  }
}

v16 이하

{
  "name": "appengine-storage",
  "description": "Node.js Google Cloud Storage sample for Google App Engine",
  "scripts": {
    "start": "node app.js",
    "test": "c8 mocha -p -j 2 system-test/*.test.js --exit --timeout=30000"
  },
  "engines": {
    "node": "16.x.x"
  },
  "dependencies": {
    "@google-cloud/storage": "^7.0.0",
    "express": "^4.18.2",
    "multer": "^1.4.5-lts.1",
    "pug": "^3.0.2"
  },
  "devDependencies": {
    "@types/express": "^4.17.17",
    "@types/multer": "^1.4.7",
    "@types/proxyquire": "^1.3.28",
    "@types/supertest": "^2.0.12",
    "@types/uuid": "^9.0.1",
    "c8": "^8.0.0",
    "mocha": "^10.2.0",
    "proxyquire": "^2.1.3",
    "supertest": "^6.3.3",
    "uuid": "^9.0.0"
  }
}

로컬에서 실행 및 테스트하는 방법은 README.md 파일을 참조하세요.

PHP

app.yaml에서 CLOUD_STORAGE_BUCKET을 설정합니다. 이 값은 이전에 만든 Cloud Storage 버킷의 이름입니다.

env_variables:
  GOOGLE_STORAGE_BUCKET: "your-bucket-name"

composer.json에서 Cloud 클라이언트 라이브러리를 포함해야 합니다. 이 라이브러리가 Cloud Storage 기능을 제공하기 때문입니다.

{
    "require": {
        "slim/slim": "^4.0",
        "slim/psr7": "^1.3",
        "google/cloud-storage": "^1.0",
        "php-di/slim-bridge": "^3.1"
    }
}

Python

app.yaml에서 GOOGLE_STORAGE_BUCKET을 설정합니다. 이 값은 이전에 만든 Cloud Storage 버킷의 이름입니다.

v3.8 이상

env_variables:
  CLOUD_STORAGE_BUCKET: [your-bucket-name]

v3.7 및 이전

env_variables:
    CLOUD_STORAGE_BUCKET: your-bucket-name

requirements.txt에서 google-cloud-storage 라이브러리를 포함해야 합니다. Cloud Storage 기능을 제공하기 때문입니다.

v3.8 이상

Flask==3.0.0
google-cloud-storage==2.9.0
gunicorn==22.0.0

v3.7 및 이전

Flask==3.0.0; python_version > '3.6'
Flask==2.0.3; python_version < '3.7'
werkzeug==3.0.1; python_version > '3.7'
werkzeug==2.3.8; python_version <= '3.7'
google-cloud-storage==2.9.0
gunicorn==22.0.0

Ruby

app.yaml에서 이전에 GCLOUD_STORAGE_BUCKET을 프로젝트용으로 만든 Cloud Storage로 설정합니다.

버전 3.2

runtime: ruby
env: flex
entrypoint: bundle exec ruby app.rb

runtime_config:
  operating_system: ubuntu22

env_variables:
  GOOGLE_CLOUD_STORAGE_BUCKET: <your-bucket-name>

버전 3.1 이하

runtime: ruby
env: flex
entrypoint: bundle exec ruby app.rb

env_variables:
  GOOGLE_CLOUD_STORAGE_BUCKET: <your-bucket-name>

Cloud Storage 기능을 사용하려면 Gemfilegcloud 라이브러리를 포함해야 합니다.

source "https://rubygems.org"

gem "google-cloud-storage"
gem "sinatra"

.NET

다음과 같이 구성합니다.

버전 6 이상

app.yaml 파일에서 TEST_GOOGLE_BUCKET_NAME을 이전에 프로젝트용으로 만든 Cloud Storage로 설정합니다.

env_variables:
  TEST_GOOGLE_BUCKET_NAME: [your-bucket-name]

버전 3.1 이하

appsettings.json에서 BucketName을 설정합니다. 이 값은 이전에 만든 Cloud Storage 버킷의 이름입니다.

{
  "GoogleCloudStorage": {
    "BucketName": "your-google-bucket-name"
  },
  "Logging": {
    "IncludeScopes": false,
    "LogLevel": {
      "Default": "Debug",
      "System": "Information",
      "Microsoft": "Information"
    }
  }
}

애플리케이션 코드

Go

샘플 애플리케이션은 웹페이지를 통해 사용자에게 Cloud Storage에 저장할 파일을 제공하라는 메시지를 표시합니다. 사용자가 파일을 선택하고 제출을 클릭하면 업로드 핸들러가 Cloud Storage NewWriter 함수를 사용하여 파일을 Cloud Storage 버킷에 씁니다.

Cloud Storage에서 이 파일을 검색하려면 버킷 이름과 파일 이름을 지정해야 합니다. 나중에 사용할 수 있도록 이 값을 앱에 저장해야 합니다.

// Copyright 2019 Google LLC
//
// Licensed under the Apache License, Version 2.0 (the "License");
// you may not use this file except in compliance with the License.
// You may obtain a copy of the License at
//
//     https://www.apache.org/licenses/LICENSE-2.0
//
// Unless required by applicable law or agreed to in writing, software
// distributed under the License is distributed on an "AS IS" BASIS,
// WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
// See the License for the specific language governing permissions and
// limitations under the License.

// Sample storage demonstrates use of the cloud.google.com/go/storage package from App Engine flexible environment.
package main

import (
	"context"
	"fmt"
	"io"
	"log"
	"net/http"
	"net/url"
	"os"

	"cloud.google.com/go/storage"
	"google.golang.org/appengine"
)

var (
	storageClient *storage.Client

	// Set this in app.yaml when running in production.
	bucket = os.Getenv("GCLOUD_STORAGE_BUCKET")
)

func main() {
	ctx := context.Background()

	var err error
	storageClient, err = storage.NewClient(ctx)
	if err != nil {
		log.Fatal(err)
	}

	http.HandleFunc("/", formHandler)
	http.HandleFunc("/upload", uploadHandler)

	appengine.Main()
}

func uploadHandler(w http.ResponseWriter, r *http.Request) {
	if r.Method != "POST" {
		http.Error(w, "", http.StatusMethodNotAllowed)
		return
	}

	ctx := appengine.NewContext(r)

	f, fh, err := r.FormFile("file")
	if err != nil {
		msg := fmt.Sprintf("Could not get file: %v", err)
		http.Error(w, msg, http.StatusBadRequest)
		return
	}
	defer f.Close()

	sw := storageClient.Bucket(bucket).Object(fh.Filename).NewWriter(ctx)
	if _, err := io.Copy(sw, f); err != nil {
		msg := fmt.Sprintf("Could not write file: %v", err)
		http.Error(w, msg, http.StatusInternalServerError)
		return
	}

	if err := sw.Close(); err != nil {
		msg := fmt.Sprintf("Could not put file: %v", err)
		http.Error(w, msg, http.StatusInternalServerError)
		return
	}

	u, _ := url.Parse("/" + bucket + "/" + sw.Attrs().Name)

	fmt.Fprintf(w, "Successful! URL: https://storage.googleapis.com%s", u.EscapedPath())
}

func formHandler(w http.ResponseWriter, r *http.Request) {
	fmt.Fprint(w, formHTML)
}

const formHTML = `<!DOCTYPE html>
<html>
  <head>
    <title>Storage</title>
    <meta charset="utf-8">
  </head>
  <body>
    <form method="POST" action="/upload" enctype="multipart/form-data">
      <input type="file" name="file">
      <input type="submit">
    </form>
  </body>
</html>`

Java

샘플 애플리케이션은 웹페이지를 통해 사용자에게 Cloud Storage에 저장할 파일을 제공하라는 메시지를 표시합니다. 사용자가 파일을 선택하고 제출을 클릭하면 doPost 요청 핸들러가 Storage.create를 사용하여 파일을 Cloud Storage 버킷에 파일을 작성합니다.다.

Cloud Storage에서 이 파일을 검색하려면 버킷 이름과 파일 이름을 지정해야 합니다. 나중에 사용할 수 있도록 이 값을 앱에 저장해야 합니다.

버전 11/17

@SuppressWarnings("serial")
@WebServlet(name = "upload", value = "/upload")
@MultipartConfig()
public class UploadServlet extends HttpServlet {

  private static final String BUCKET_NAME =
      System.getenv().getOrDefault("BUCKET_NAME", "my-test-bucket");
  private static Storage storage = null;

  public UploadServlet() {
    storage = StorageOptions.getDefaultInstance().getService();
  }

  @Override
  public void doPost(HttpServletRequest req, HttpServletResponse resp)
      throws IOException, ServletException {
    final Part filePart = req.getPart("file");
    final String fileName = filePart.getSubmittedFileName();
    // Modify access list to allow all users with link to read file
    List<Acl> acls = new ArrayList<>();
    acls.add(Acl.of(Acl.User.ofAllUsers(), Acl.Role.READER));
    // the inputstream is closed by default, so we don't need to close it here
    Blob blob =
        storage.create(
            BlobInfo.newBuilder(BUCKET_NAME, fileName).setAcl(acls).build(),
            filePart.getInputStream());

    // return the public download link
    resp.getWriter().print(blob.getMediaLink());
  }
}

버전 8

@SuppressWarnings("serial")
@WebServlet(name = "upload", value = "/upload")
@MultipartConfig()
public class UploadServlet extends HttpServlet {

  private static final String BUCKET_NAME = System.getenv("BUCKET_NAME");
  private static Storage storage = null;

  @Override
  public void init() {
    storage = StorageOptions.getDefaultInstance().getService();
  }

  @Override
  public void doPost(HttpServletRequest req, HttpServletResponse resp)
      throws IOException, ServletException {
    final Part filePart = req.getPart("file");
    final String fileName = filePart.getSubmittedFileName();

    // Modify access list to allow all users with link to read file
    List<Acl> acls = new ArrayList<>();
    acls.add(Acl.of(Acl.User.ofAllUsers(), Acl.Role.READER));
    // the inputstream is closed by default, so we don't need to close it here
    Blob blob =
        storage.create(
            BlobInfo.newBuilder(BUCKET_NAME, fileName).setAcl(acls).build(),
            filePart.getInputStream());

    // return the public download link
    resp.getWriter().print(blob.getMediaLink());
  }
}

Node.js

샘플 애플리케이션은 웹페이지를 통해 사용자에게 Cloud Storage에 저장할 파일을 제공하라는 메시지를 표시합니다. 사용자가 파일을 선택하고 제출을 클릭하면 업로드 핸들러가 파일 콘텐츠를 BLOB에 로드하고 이를 Cloud Storage에 작성합니다.

파일이 Cloud Storage에 업로드된 후에는 이 파일의 공개 URL이 반환되며, 이 URL을 사용하여 Cloud Storage에서 직접 파일을 제공할 수 있습니다. 나중에 사용할 수 있도록 이 값을 앱에 저장해야 합니다.

const {format} = require('util');
const express = require('express');
const Multer = require('multer');

// By default, the client will authenticate using the service account file
// specified by the GOOGLE_APPLICATION_CREDENTIALS environment variable and use
// the project specified by the GOOGLE_CLOUD_PROJECT environment variable. See
// https://github.com/GoogleCloudPlatform/google-cloud-node/blob/master/docs/authentication.md
// These environment variables are set automatically on Google App Engine
const {Storage} = require('@google-cloud/storage');

// Instantiate a storage client
const storage = new Storage();

const app = express();
app.set('view engine', 'pug');

// This middleware is available in Express v4.16.0 onwards
app.use(express.json());

// Multer is required to process file uploads and make them available via
// req.files.
const multer = Multer({
  storage: Multer.memoryStorage(),
  limits: {
    fileSize: 5 * 1024 * 1024, // no larger than 5mb, you can change as needed.
  },
});

// A bucket is a container for objects (files).
const bucket = storage.bucket(process.env.GCLOUD_STORAGE_BUCKET);

// Display a form for uploading files.
app.get('/', (req, res) => {
  res.render('form.pug');
});

// Process the file upload and upload to Google Cloud Storage.
app.post('/upload', multer.single('file'), (req, res, next) => {
  if (!req.file) {
    res.status(400).send('No file uploaded.');
    return;
  }

  // Create a new blob in the bucket and upload the file data.
  const blob = bucket.file(req.file.originalname);
  const blobStream = blob.createWriteStream();

  blobStream.on('error', err => {
    next(err);
  });

  blobStream.on('finish', () => {
    // The public URL can be used to directly access the file via HTTP.
    const publicUrl = format(
      `https://storage.googleapis.com/${bucket.name}/${blob.name}`
    );
    res.status(200).send(publicUrl);
  });

  blobStream.end(req.file.buffer);
});

const PORT = parseInt(process.env.PORT) || 8080;
app.listen(PORT, () => {
  console.log(`App listening on port ${PORT}`);
  console.log('Press Ctrl+C to quit.');
});

PHP

샘플 애플리케이션은 웹페이지를 통해 사용자에게 Cloud Storage에 저장할 파일을 제공하라는 메시지를 표시합니다. 사용자가 파일을 선택하고 제출을 클릭하면 업로드 핸들러가 파일 콘텐츠를 BLOB에 로드하고 이를 Cloud Storage에 작성합니다.

파일이 Cloud Storage에 업로드된 후에는 이 파일의 공개 URL이 반환되며, 이 URL을 사용하여 Cloud Storage에서 직접 파일을 제공할 수 있습니다. 나중에 사용할 수 있도록 이 값을 앱에 저장해야 합니다.

use DI\Container;
use Google\Cloud\Storage\StorageClient;
use Psr\Http\Message\ServerRequestInterface as Request;
use Psr\Http\Message\ResponseInterface as Response;
use Slim\Factory\AppFactory;

// Create App
AppFactory::setContainer($container = new Container());
$app = AppFactory::create();

// Display errors
$app->addErrorMiddleware(true, true, true);

$container = $app->getContainer();

$app->get('/', function (Request $request, Response $response) use ($container) {
    /** @var Google\Cloud\StorageClient */
    $storage = $container->get('storage');
    $bucketName = $container->get('bucket_name');
    $objectName = $container->get('object_name');
    $bucket = $storage->bucket($bucketName);
    $object = $bucket->object($objectName);
    $content = $object->exists() ? $object->downloadAsString() : '';
    $escapedContent = htmlspecialchars($content);
    $response->getBody()->write(<<<EOF
    <h1>Storage Example</h1>
    <h3>Write [<a href="https://cloud.google.com/appengine/docs/flexible/php/using-cloud-storage">docs</a>]:</h3>
    <form action="/write" method="post">
        Some file content:<br />
        <textarea name="content"></textarea><br />
        <input type="submit" />
    </form>
EOF
    );
    if ($content) {
        $response->getBody()->write(
            "<p><strong>Your content:</strong><p><p>$escapedContent</p>"
        );
    }
    return $response;
});

/**
 * Write to a Storage bucket.
 * @see https://cloud.google.com/appengine/docs/flexible/php/using-cloud-storage
 */
$app->post('/write', function (Request $request, Response $response) use ($container) {
    /** @var Google\Cloud\StorageClient */
    $storage = $container->get('storage');
    $bucketName = $container->get('bucket_name');
    $objectName = $container->get('object_name');
    parse_str((string) $request->getBody(), $postData);
    $metadata = ['contentType' => 'text/plain'];
    $storage->bucket($bucketName)->upload($postData['content'] ?? '', [
        'name' => $objectName,
        'metadata' => $metadata,
    ]);
    return $response
        ->withStatus(302)
        ->withHeader('Location', '/');
});

$container->set('storage', function () use ($container) {
    $projectId = $container->get('project_id');
    $storage = new StorageClient([
        'projectId' => $projectId
    ]);
    return $storage;
});

Python

샘플 애플리케이션은 웹페이지를 통해 사용자에게 Cloud Storage에 저장할 파일을 제공하라는 메시지를 표시합니다. 사용자가 파일을 선택하고 제출을 클릭하면 업로드 핸들러가 파일 콘텐츠를 Cloud Storage blob에 로드하고 Cloud Storage 버킷에 씁니다.

파일이 Cloud Storage에 업로드된 후에는 이 파일의 공개 URL이 반환되며, 이 URL을 사용하여 Cloud Storage에서 직접 파일을 제공할 수 있습니다. 나중에 사용할 수 있도록 이 값을 앱에 저장해야 합니다.

v3.8 이상

from __future__ import annotations

import logging
import os

from flask import Flask, request
from google.cloud import storage

app = Flask(__name__)

# Configure this environment variable via app.yaml
CLOUD_STORAGE_BUCKET = os.environ["CLOUD_STORAGE_BUCKET"]

@app.route("/")
def index() -> str:
    return """
<form method="POST" action="/upload" enctype="multipart/form-data">
    <input type="file" name="file">
    <input type="submit">
</form>
"""

@app.route("/upload", methods=["POST"])
def upload() -> str:
    """Process the uploaded file and upload it to Google Cloud Storage."""
    uploaded_file = request.files.get("file")

    if not uploaded_file:
        return "No file uploaded.", 400

    # Create a Cloud Storage client.
    gcs = storage.Client()

    # Get the bucket that the file will be uploaded to.
    bucket = gcs.get_bucket(CLOUD_STORAGE_BUCKET)

    # Create a new blob and upload the file's content.
    blob = bucket.blob(uploaded_file.filename)

    blob.upload_from_string(
        uploaded_file.read(), content_type=uploaded_file.content_type
    )

    # Make the blob public. This is not necessary if the
    # entire bucket is public.
    # See https://cloud.google.com/storage/docs/access-control/making-data-public.
    blob.make_public()

    # The public URL can be used to directly access the uploaded file via HTTP.
    return blob.public_url

@app.errorhandler(500)
def server_error(e: Exception | int) -> str:
    logging.exception("An error occurred during a request.")
    return (
        """
    An internal error occurred: <pre>{}</pre>
    See logs for full stacktrace.
    """.format(
            e
        ),
        500,
    )

if __name__ == "__main__":
    # This is used when running locally. Gunicorn is used to run the
    # application on Google App Engine. See entrypoint in app.yaml.
    app.run(host="127.0.0.1", port=8080, debug=True)

v3.7 및 이전

from __future__ import annotations

import logging
import os

from flask import Flask, request
from google.cloud import storage

app = Flask(__name__)

# Configure this environment variable via app.yaml
CLOUD_STORAGE_BUCKET = os.environ["CLOUD_STORAGE_BUCKET"]

@app.route("/")
def index() -> str:
    return """
<form method="POST" action="/upload" enctype="multipart/form-data">
    <input type="file" name="file">
    <input type="submit">
</form>
"""

@app.route("/upload", methods=["POST"])
def upload() -> str:
    """Process the uploaded file and upload it to Google Cloud Storage."""
    uploaded_file = request.files.get("file")

    if not uploaded_file:
        return "No file uploaded.", 400

    # Create a Cloud Storage client.
    gcs = storage.Client()

    # Get the bucket that the file will be uploaded to.
    bucket = gcs.get_bucket(CLOUD_STORAGE_BUCKET)

    # Create a new blob and upload the file's content.
    blob = bucket.blob(uploaded_file.filename)

    blob.upload_from_string(
        uploaded_file.read(), content_type=uploaded_file.content_type
    )

    # Make the blob public. This is not necessary if the
    # entire bucket is public.
    # See https://cloud.google.com/storage/docs/access-control/making-data-public.
    blob.make_public()

    # The public URL can be used to directly access the uploaded file via HTTP.
    return blob.public_url

@app.errorhandler(500)
def server_error(e: Exception | int) -> str:
    logging.exception("An error occurred during a request.")
    return (
        """
    An internal error occurred: <pre>{}</pre>
    See logs for full stacktrace.
    """.format(
            e
        ),
        500,
    )

if __name__ == "__main__":
    # This is used when running locally. Gunicorn is used to run the
    # application on Google App Engine. See entrypoint in app.yaml.
    app.run(host="127.0.0.1", port=8080, debug=True)

Ruby

샘플 애플리케이션은 웹페이지를 통해 사용자에게 Cloud Storage에 저장할 파일을 제공하라는 메시지를 표시합니다. 사용자가 파일을 선택하고 제출을 클릭하면 업로드 핸들러가 파일 콘텐츠를 BLOB에 로드하고 이를 Cloud Storage에 작성합니다.

파일이 Cloud Storage에 업로드된 후에는 이 파일의 공개 URL이 반환되며, 이 URL을 사용하여 Cloud Storage에서 직접 파일을 제공할 수 있습니다. 나중에 사용할 수 있도록 이 값을 앱에 저장해야 합니다.

require "sinatra"
require "google/cloud/storage"

storage = Google::Cloud::Storage.new
bucket  = storage.bucket ENV["GOOGLE_CLOUD_STORAGE_BUCKET"]

get "/" do
  # Present the user with an upload form
  '
    <form method="POST" action="/upload" enctype="multipart/form-data">
      <input type="file" name="file">
      <input type="submit" value="Upload">
    </form>
  '
end

post "/upload" do
  file_path = params[:file][:tempfile].path
  file_name = params[:file][:filename]

  # Upload file to Google Cloud Storage bucket
  file = bucket.create_file file_path, file_name, acl: "public"

  # The public URL can be used to directly access the uploaded file via HTTP
  file.public_url
end

.NET

샘플 애플리케이션은 웹페이지를 통해 사용자에게 Cloud Storage에 저장할 파일을 제공하라는 메시지를 표시합니다. 사용자가 파일을 선택하고 제출을 클릭하면 업로드 핸들러가 파일 콘텐츠를 BLOB에 로드하고 이를 Cloud Storage에 작성합니다.

파일이 Cloud Storage에 업로드된 후에는 이 파일의 공개 URL이 반환되며, 이 URL을 사용하여 Cloud Storage에서 직접 파일을 제공할 수 있습니다. 나중에 사용할 수 있도록 이 값을 앱에 저장해야 합니다.

버전 6 이상

    public class HomeController : Controller
    {
        // Contains the bucket name and object name
        readonly CloudStorageOptions _options;
        // The Google Cloud Storage client.
        readonly StorageClient _storage;

        public HomeController(CloudStorageOptions options)
        {
            _options = options;
            _storage = StorageClient.Create();
        }

        [HttpGet]
        public async Task<IActionResult> Index()
        {
            var model = new HomeIndex();
            if (new string[] { null, "", "your-google-bucket-name" }
                .Contains(_options.BucketName))
            {
                model.MissingBucketName = true;
                return View(model);
            }
            try
            {
                // Get the storage object.
                var storageObject =
                    await _storage.GetObjectAsync(_options.BucketName, _options.ObjectName);
                // Get a direct link to the storage object.
                model.MediaLink = storageObject.MediaLink;
                // Download the storage object.
                MemoryStream m = new MemoryStream();
                await _storage.DownloadObjectAsync(
                    _options.BucketName, _options.ObjectName, m);
                m.Seek(0, SeekOrigin.Begin);
                byte[] content = new byte[m.Length];
                m.Read(content, 0, content.Length);
                model.Content = Encoding.UTF8.GetString(content);
            }
            catch (GoogleApiException e)
            when (e.HttpStatusCode == System.Net.HttpStatusCode.NotFound)
            {
                // Does not exist yet.  No problem.
            }
            return View(model);
        }

        [HttpPost]
        public async Task<IActionResult> Index(Form sendForm)
        {
            var model = new HomeIndex();
            // Take the content uploaded in the form and upload it to
            // Google Cloud Storage.
            await _storage.UploadObjectAsync(
                _options.BucketName, _options.ObjectName, "text/plain",
                new MemoryStream(Encoding.UTF8.GetBytes(sendForm.Content)));
            model.Content = sendForm.Content;
            model.SavedNewContent = true;
            var storageObject =
                await _storage.GetObjectAsync(_options.BucketName, _options.ObjectName);
            model.MediaLink = storageObject.MediaLink;
            return View(model);
        }

버전 3.1 이하

    public class HomeController : Controller
    {
        // Contains the bucket name and object name
        readonly CloudStorageOptions _options;
        // The Google Cloud Storage client.
        readonly StorageClient _storage;

        public HomeController(IOptions<CloudStorageOptions> options)
        {
            _options = options.Value;
            _storage = StorageClient.Create();
        }

        [HttpGet]
        public async Task<IActionResult> Index()
        {
            var model = new HomeIndex();
            if (new string[] { null, "", "your-google-bucket-name" }
                .Contains(_options.BucketName))
            {
                model.MissingBucketName = true;
                return View(model);
            }
            try
            {
                // Get the storage object.
                var storageObject =
                    await _storage.GetObjectAsync(_options.BucketName, _options.ObjectName);
                // Get a direct link to the storage object.
                model.MediaLink = storageObject.MediaLink;
                // Download the storage object.
                MemoryStream m = new MemoryStream();
                await _storage.DownloadObjectAsync(
                    _options.BucketName, _options.ObjectName, m);
                m.Seek(0, SeekOrigin.Begin);
                byte[] content = new byte[m.Length];
                m.Read(content, 0, content.Length);
                model.Content = Encoding.UTF8.GetString(content);
            }
            catch (GoogleApiException e)
            when (e.HttpStatusCode == System.Net.HttpStatusCode.NotFound)
            {
                // Does not exist yet.  No problem.
            }
            return View(model);
        }

        [HttpPost]
        public async Task<IActionResult> Index(Form sendForm)
        {
            var model = new HomeIndex();
            // Take the content uploaded in the form and upload it to
            // Google Cloud Storage.
            await _storage.UploadObjectAsync(
                _options.BucketName, _options.ObjectName, "text/plain",
                new MemoryStream(Encoding.UTF8.GetBytes(sendForm.Content)));
            model.Content = sendForm.Content;
            model.SavedNewContent = true;
            var storageObject =
                await _storage.GetObjectAsync(_options.BucketName, _options.ObjectName);
            model.MediaLink = storageObject.MediaLink;
            return View(model);
        }

자연어 처리와 디코더-인코더,

Cloud Storage에 대한 자세한 내용은 Cloud Storage 문서를 참조하세요.