GCSからファイルを取得してarchiveする
This commit is contained in:
parent
f1f4de1684
commit
7febf69c0c
3
.gitignore
vendored
3
.gitignore
vendored
@ -133,4 +133,5 @@ dist
|
||||
csv_output/
|
||||
output/
|
||||
output.*
|
||||
docments/
|
||||
docments/
|
||||
keys/
|
138
docs/cloudStorageByNode.md
Normal file
138
docs/cloudStorageByNode.md
Normal file
@ -0,0 +1,138 @@
|
||||
# [GCP][GCS]Node.jsライブラリでストレージを活用する
|
||||
|
||||
Node.jsのライブラリを使いストレージを制御します
|
||||
|
||||
## GCSとの連携について
|
||||
|
||||
セキュリティやアクセス制御の観点から、
|
||||
フロントエンドは直接Cloud Storageにアクセスせず
|
||||
サーバー経由で取得するのが一般的です
|
||||
|
||||
ただし静的なファイルや公開データであれば
|
||||
フロントエンドから直接Cloud Storageにアクセスすることもあります
|
||||
|
||||
## ライブラリのインストール
|
||||
|
||||
```sh
|
||||
npm install --save @google-cloud/storage
|
||||
```
|
||||
|
||||
## GCS接続
|
||||
|
||||
```js
|
||||
const { Storage } = require('@google-cloud/storage');
|
||||
```
|
||||
|
||||
**サービスアカウントを環境変数で設定する場合**
|
||||
|
||||
```sh
|
||||
export GOOGLE_APPLICATION_CREDENTIALS="/path/to/service-account.json"
|
||||
```
|
||||
|
||||
```js
|
||||
const storage = new Storage()
|
||||
```
|
||||
|
||||
**JSONキーファイルをソースで読み込む場合**
|
||||
|
||||
```js
|
||||
const KEY_FILE_PATH = './keys/service-account.json'
|
||||
|
||||
const storage = new Storage({
|
||||
keyFilename: KEY_FILE_PATH});
|
||||
```
|
||||
|
||||
**JSONキーファイルを使わず直接設定**
|
||||
|
||||
```js
|
||||
const serviceAccount = {
|
||||
type: "service_account",
|
||||
project_id: "your-project-id",
|
||||
private_key_id: "your-private-key-id",
|
||||
private_key: "-----BEGIN PRIVATE KEY-----\nYOUR-PRIVATE-KEY\n-----END PRIVATE KEY-----\n",
|
||||
client_email: "your-service-account@your-project-id.iam.gserviceaccount.com",
|
||||
client_id: "your-client-id",
|
||||
auth_uri: "https://accounts.google.com/o/oauth2/auth",
|
||||
token_uri: "https://oauth2.googleapis.com/token",
|
||||
auth_provider_x509_cert_url: "https://www.googleapis.com/oauth2/v1/certs",
|
||||
client_x509_cert_url: "https://www.googleapis.com/robot/v1/metadata/x509/your-service-account"
|
||||
};
|
||||
const storage = new Storage({ credentials: serviceAccount });
|
||||
```
|
||||
|
||||
## 権限について
|
||||
|
||||
* ストレージ管理者
|
||||
*
|
||||
* 環境とストレージ オブジェクト閲覧者
|
||||
* Storage オブジェクト閲覧者
|
||||
* ストレージ フォルダ管理者
|
||||
|
||||
## サンプルコード
|
||||
|
||||
### バケット一覧を取得する
|
||||
|
||||
```js
|
||||
/**
|
||||
* バケット一覧を取得する
|
||||
*/
|
||||
async function listBuckets() {
|
||||
const [buckets] = await storage.getBuckets();
|
||||
|
||||
console.log('Buckets:');
|
||||
buckets.forEach(bucket => {
|
||||
console.log(bucket.name);
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
ファイル検索については以下のページを参照してください
|
||||
[[GCP]Google Cloud Storageでパターンにマッチしたファイル一覧を取得する](https://wiki.pglikers.com/en/private/cloud/gcp/gcs/glob)
|
||||
|
||||
|
||||
|
||||
### バケットの中のファイル一覧を取得する
|
||||
|
||||
```js
|
||||
async function listFiles(bucketName) {
|
||||
const [files] = await storage.bucket(bucketName).getFiles();
|
||||
|
||||
console.log(`Files in ${bucketName}:`);
|
||||
files.forEach(file => {
|
||||
console.log(file.name);
|
||||
});
|
||||
}
|
||||
```
|
||||
|
||||
### 署名付きURLを発行する
|
||||
|
||||
```js
|
||||
/**
|
||||
* 署名付きURLを生成する
|
||||
*/
|
||||
const generateV4ReadSignedUrl = async (bucketName, fileName) => {
|
||||
const options = {
|
||||
version: 'v4',
|
||||
action: 'read',
|
||||
expires: Date.now() + 15 * 60 * 1000, // 15 minutes
|
||||
};
|
||||
const [url] = await storage.bucket(bucketName).file(fileName).getSignedUrl(options);
|
||||
console.log(`Generated GET signed URL:`);
|
||||
console.log(url);
|
||||
return url;
|
||||
}
|
||||
```
|
||||
|
||||
### ファイルをダウンロードする
|
||||
|
||||
```js
|
||||
// ファイルのコンテンツをダウンロードする
|
||||
const downloadFile = async () => {
|
||||
const options = {
|
||||
destination: path.join(__dirname, FILE_NAME)
|
||||
};
|
||||
await storage.bucket(BUCKET_NAME).file(FILE_NAME).download(options);
|
||||
// 取得したファイルのコンテンツからファイルを生成する
|
||||
console.log(`Downloaded ${FILE_NAME}`);
|
||||
};
|
||||
```
|
15
package-lock.json
generated
15
package-lock.json
generated
@ -11,7 +11,8 @@
|
||||
"dependencies": {
|
||||
"@google-cloud/storage": "^7.15.2",
|
||||
"archiver": "^7.0.1",
|
||||
"csv-writer": "^1.6.0"
|
||||
"csv-writer": "^1.6.0",
|
||||
"dotenv": "^16.4.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jsdoc": "^4.0.4"
|
||||
@ -601,6 +602,18 @@
|
||||
"node": ">=0.4.0"
|
||||
}
|
||||
},
|
||||
"node_modules/dotenv": {
|
||||
"version": "16.4.7",
|
||||
"resolved": "https://registry.npmjs.org/dotenv/-/dotenv-16.4.7.tgz",
|
||||
"integrity": "sha512-47qPchRCykZC03FhkYAhrvwU4xDBFIj1QPqaarj6mdM/hgUzfPHcpkHJOn3mJAufFeeAxAzeGsr5X0M4k6fLZQ==",
|
||||
"license": "BSD-2-Clause",
|
||||
"engines": {
|
||||
"node": ">=12"
|
||||
},
|
||||
"funding": {
|
||||
"url": "https://dotenvx.com"
|
||||
}
|
||||
},
|
||||
"node_modules/dunder-proto": {
|
||||
"version": "1.0.1",
|
||||
"resolved": "https://registry.npmjs.org/dunder-proto/-/dunder-proto-1.0.1.tgz",
|
||||
|
@ -2,11 +2,12 @@
|
||||
"name": "js-common-code",
|
||||
"version": "1.0.0",
|
||||
"description": "Javascriptで活用できるコードを開発する。 Node.jsによりサーバーサイドも作成する",
|
||||
"main": "src/server/hellp.js",
|
||||
"main": "src/server/index.js",
|
||||
"directories": {
|
||||
"doc": "docs"
|
||||
},
|
||||
"scripts": {
|
||||
"dev": "node src/server/index.js",
|
||||
"test": "echo \"Error: no test specified\" && exit 1"
|
||||
},
|
||||
"author": "",
|
||||
@ -14,7 +15,8 @@
|
||||
"dependencies": {
|
||||
"@google-cloud/storage": "^7.15.2",
|
||||
"archiver": "^7.0.1",
|
||||
"csv-writer": "^1.6.0"
|
||||
"csv-writer": "^1.6.0",
|
||||
"dotenv": "^16.4.7"
|
||||
},
|
||||
"devDependencies": {
|
||||
"jsdoc": "^4.0.4"
|
||||
|
0
src/front/assets/cloud-storage.js
Normal file
0
src/front/assets/cloud-storage.js
Normal file
BIN
src/front/assets/data/test.zip
Normal file
BIN
src/front/assets/data/test.zip
Normal file
Binary file not shown.
@ -14,6 +14,7 @@
|
||||
<p >Server </p>
|
||||
<button id="download-button-server">Zip Download(From Server)</button>
|
||||
<button id="download-button-upload">Zip Download(upload)</button>
|
||||
<p >Google Storage Link</p>
|
||||
<script src="assets/download.js"></script>
|
||||
<script src="assets/downloadFromServer.js"></script>
|
||||
</body>
|
||||
|
15
src/front/gcs.html
Normal file
15
src/front/gcs.html
Normal file
@ -0,0 +1,15 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="en">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<script src="https://cdnjs.cloudflare.com/ajax/libs/jszip/3.10.1/jszip.min.js"></script>
|
||||
<title>Google Cloud Storage</title>
|
||||
</head>
|
||||
<body>
|
||||
<h1>JavaScript Develop Download To Google Cloud Storage</h1>
|
||||
<p >Zip File Download</p>
|
||||
<button id="download-button">Zip Download(GCS)</button>
|
||||
<script src="assets/cloud-storage.js"></script>
|
||||
</body>
|
||||
</html>
|
26
src/script/gcs.js
Normal file
26
src/script/gcs.js
Normal file
@ -0,0 +1,26 @@
|
||||
/**
|
||||
* @fileoverview Google Cloud Storage (GCS) download module.
|
||||
*/
|
||||
const path = require('path');
|
||||
const { Storage } = require('@google-cloud/storage');
|
||||
|
||||
const KEY_FILE_PATH = './keys/service-account.json'
|
||||
// バケット名、ファイル名を.envから取得する
|
||||
const BUCKET_NAME = process.env.BUCKET_NAME;
|
||||
const FILE_NAME = process.env.FILE_NAME;
|
||||
|
||||
|
||||
const storage = new Storage({
|
||||
keyFilename: KEY_FILE_PATH});
|
||||
|
||||
// ファイルのコンテンツをダウンロードする
|
||||
const downloadFile = async () => {
|
||||
const options = {
|
||||
destination: path.join(__dirname, FILE_NAME)
|
||||
};
|
||||
await storage.bucket(BUCKET_NAME).file(FILE_NAME).download(options);
|
||||
// 取得したファイルのコンテンツからファイルを生成する
|
||||
console.log(`Downloaded ${FILE_NAME}`);
|
||||
};
|
||||
downloadFile();
|
||||
|
@ -8,7 +8,7 @@ const path = require('path');
|
||||
* @param {http.ServerResponse} res
|
||||
* @returns {void}
|
||||
*/
|
||||
const downdloadContents = (req, res) => {
|
||||
const downloadContents = (req, res) => {
|
||||
|
||||
// ファイルの圧縮処理
|
||||
// CORSヘッダーを追加
|
||||
@ -87,5 +87,7 @@ const generateZipUrl = (req, res) => {
|
||||
}
|
||||
|
||||
|
||||
module.exports = downdloadContents;
|
||||
module.exports = generateZipUrl;
|
||||
module.exports = {
|
||||
downloadContents,
|
||||
generateZipUrl
|
||||
};
|
||||
|
46
src/server/download/gcsArchive.js
Normal file
46
src/server/download/gcsArchive.js
Normal file
@ -0,0 +1,46 @@
|
||||
/**
|
||||
* @fileoverview Google Cloud Storage (GCS) download module.
|
||||
*/
|
||||
const { Storage } = require('@google-cloud/storage');
|
||||
const archiver = require('archiver');
|
||||
const KEY_FILE_PATH = './keys/service-account.json'
|
||||
const storage = new Storage({
|
||||
keyFilename: KEY_FILE_PATH});
|
||||
|
||||
// Load environment variables
|
||||
require('dotenv').config();
|
||||
|
||||
// バケット名を.envから取得する
|
||||
const BUCKET_NAME = process.env.BUCKET_NAME;
|
||||
console.log(`BUCKET_NAME: ${BUCKET_NAME}`);
|
||||
|
||||
|
||||
/**
|
||||
* GCStorageからファイルをダウンロードする
|
||||
*
|
||||
* @param {http.IncomingMessage} req
|
||||
* @param {http.ServerResponse} res
|
||||
*/
|
||||
const downloadFilesFromGCS = async (req, res) => {
|
||||
// バケットからファイル一覧を取得する
|
||||
const [files] = await storage.bucket(BUCKET_NAME).getFiles();
|
||||
const filesToZip = files.map((file) => file.name);
|
||||
|
||||
res.setHeader('Content-Disposition', 'attachment; filename="files.zip"');
|
||||
res.setHeader('Content-Type', 'application/zip');
|
||||
|
||||
const archive = archiver('zip', { zlib: { level: 9 } });
|
||||
|
||||
archive.on('error', (err) => res.status(500).send({ error: err.message }));
|
||||
archive.pipe(res);
|
||||
|
||||
|
||||
for (const fileName of filesToZip) {
|
||||
const file = storage.bucket(BUCKET_NAME).file(fileName);
|
||||
archive.append(file.createReadStream(), { name: fileName });
|
||||
}
|
||||
archive.finalize();
|
||||
};
|
||||
|
||||
|
||||
module.exports = downloadFilesFromGCS;
|
@ -1,8 +1,8 @@
|
||||
const http = require('http');
|
||||
// download/download.jsのdowndloadContentsメソッドをインポート
|
||||
const downdloadContents = require('./download/download');
|
||||
// download/download.jsのgenerateZipUrlメソッドをインポート
|
||||
const generateZipUrl = require('./download/download');
|
||||
|
||||
const { downloadContents, generateZipUrl } = require('./download/download');
|
||||
const downloadFilesFromGCS = require('./download/gcsArchive');
|
||||
|
||||
|
||||
|
||||
/**
|
||||
@ -17,11 +17,13 @@ const server = http.createServer((req, res) => {
|
||||
res.end('Hello World\n');
|
||||
} else if (req.url === '/downdload') {
|
||||
// ZIPファイルのコンテンツをそのまま返す
|
||||
downdloadContents(req, res);
|
||||
downloadContents(req, res);
|
||||
} else if (req.url === '/generate-zip') {
|
||||
// ZIPファイルの生成してストレージのURLを返す
|
||||
generateZipUrl(req, res);
|
||||
|
||||
} else if (req.url === '/downdload-gcs') {
|
||||
// GCSからZIPファイルのコンテンツをそのまま返す
|
||||
downloadFilesFromGCS(req, res);
|
||||
} else {
|
||||
res.statusCode = 404;
|
||||
res.setHeader('Content-Type', 'text/plain');
|
||||
@ -32,4 +34,6 @@ const server = http.createServer((req, res) => {
|
||||
const port = 3000;
|
||||
server.listen(port, () => {
|
||||
console.log(`Server running at http://localhost:${port}/`);
|
||||
});
|
||||
});
|
||||
|
||||
|
||||
|
Loading…
x
Reference in New Issue
Block a user