From 7f74ac7be33acbf3133e7eb4d78cd14b11ecc982 Mon Sep 17 00:00:00 2001 From: Tem Taepaisitphongse Date: Thu, 16 Sep 2021 18:53:44 -0400 Subject: [PATCH 01/11] update: upload and download with aws s3 --- package.json | 1 + src/config/s3.ts | 12 ++++++++++++ src/controllers/file.ts | 5 +++-- src/middlewares/README.md | 27 +++++++++++++++++++++++++-- src/middlewares/download.ts | 25 ++++++++++++++----------- src/middlewares/upload.ts | 25 +++++++++++-------------- src/routes/file.ts | 2 +- 7 files changed, 67 insertions(+), 30 deletions(-) create mode 100644 src/config/s3.ts diff --git a/package.json b/package.json index dc65f01..f85aba1 100644 --- a/package.json +++ b/package.json @@ -41,6 +41,7 @@ "@types/body-parser": "^1.19.1", "@types/morgan": "^1.9.3", "@types/multer": "^1.4.7", + "aws-sdk": "^2.990.0", "axios": "^0.21.1", "bcryptjs": "^2.4.3", "body-parser": "^1.19.0", diff --git a/src/config/s3.ts b/src/config/s3.ts new file mode 100644 index 0000000..d0a782d --- /dev/null +++ b/src/config/s3.ts @@ -0,0 +1,12 @@ +import AWS from 'aws-sdk'; +import dotenv from 'dotenv'; + +dotenv.config(); + +const s3 = new AWS.S3({ + accessKeyId: process.env.AWS_ACCESS_KEY_ID, + secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY, + region: process.env.AWS_DEFAULT_REGION +}); + +export default s3; \ No newline at end of file diff --git a/src/controllers/file.ts b/src/controllers/file.ts index 9d1394d..6bfacce 100644 --- a/src/controllers/file.ts +++ b/src/controllers/file.ts @@ -18,8 +18,9 @@ export default { }, download: async (req: Request, res: Response) => { try { - const filePath = req.params.filePath; - await download(`${filePath}`, req, res); + const filePath = 'ml/filename'; + + await download(filePath, req, res); } catch (err) { res .status(500) diff --git a/src/middlewares/README.md b/src/middlewares/README.md index 0a9f8c8..df14d7f 100644 --- a/src/middlewares/README.md +++ b/src/middlewares/README.md @@ -1,4 +1,4 @@ -# Upload to Google Cloud Storage +# Upload to AWS S3 ## Import @@ -21,5 +21,28 @@ upload(buffer, path, name) import upload from '../middlewares/upload'; const URI = await upload(buffer, "folder1/folder2", "testfile"); -console.log(URI); // { "url": "https://storage.cloud.google.com/stroke_images_3/folder1/folder2/testfile.ext", "gsutilURI": "gs://stroke_images_3/folder1/folder2/testfile.ext" } +console.log(URI); // { "url": "s3://app4stroke/folder1/folder2/testfile.ext", "gsutilURI": "https://app4stroke.s3.ap-southeast-1.amazonaws.com/folder1/folder2/testfile.ext" } ``` + +# Download from AWS S3 + +## Import + +```typescript +import download from '../middlewares/download'; + +``` + +## Usage +` +download(filePath, req, res) +` + +- filePath : string + +## Example +```typescript +import download from '../middlewares/download'; + +await download("folder1/folder2/testfile.ext", req, res); +``` \ No newline at end of file diff --git a/src/middlewares/download.ts b/src/middlewares/download.ts index 0d05b44..7c1d78f 100644 --- a/src/middlewares/download.ts +++ b/src/middlewares/download.ts @@ -1,22 +1,25 @@ import { Request, Response } from 'express'; import httpError from '../errorHandler/httpError/httpError'; -import bucket from '../config/storage'; + +import s3 from '../config/s3'; const download = async (filePath: string, req: Request, res: Response) => { try { - const file = bucket.file(filePath); - const readStream = file.createReadStream(); + const params = { + Bucket: "app4stroke", + Key: filePath + } - await file - .getMetadata() - .then((metadata) => { - res.setHeader("content-type", metadata[0].contentType); - readStream.pipe(res); - }); + res.setHeader('Content-Disposition', 'attachment'); + s3.getObject(params) + .createReadStream() + .on('error', function(err){ + res.status(500).send(httpError(500, "Error: " + err)); + }).pipe(res); } catch (err) { - res.status(404).send(httpError(404, "No such file found.")); + res.status(404).send(httpError(404, "The file could not be accessed.")); } -} +}; export default download; \ No newline at end of file diff --git a/src/middlewares/upload.ts b/src/middlewares/upload.ts index 8aa4656..42574a6 100644 --- a/src/middlewares/upload.ts +++ b/src/middlewares/upload.ts @@ -1,6 +1,6 @@ -import bucket from '../config/storage'; import path from 'path'; import FileType from 'file-type'; +import s3 from '../config/s3'; const upload = async (buffer: any, filePath: string, fileName: string) => { const { ext, mime } = (await FileType.fromBuffer(buffer)) || { @@ -9,21 +9,18 @@ const upload = async (buffer: any, filePath: string, fileName: string) => { }; const fullPath = path.join(filePath, fileName + '.' + ext); - const file = bucket.file(fullPath); - return new Promise((resolve, reject) => { - file - .save(buffer) - .then(() => { - resolve({ - url: `https://storage.cloud.google.com/stroke_images_3/${fullPath}`, - gsutilURI: `gs://stroke_images_3/${fullPath}`, - }); - }) - .catch(() => { - reject({}); - }); + var params = { + Bucket: "app4stroke", + Key: fullPath, + Body: buffer, + }; + + s3.putObject(params, function(err) { + if (err) console.log(err); }); + + return { url: `s3://app4stroke/${fullPath}`, gsutilURI: `https://app4stroke.s3.ap-southeast-1.amazonaws.com/${fullPath}` }; }; export default upload; diff --git a/src/routes/file.ts b/src/routes/file.ts index dff1d66..1c1bc91 100644 --- a/src/routes/file.ts +++ b/src/routes/file.ts @@ -4,6 +4,6 @@ import fileController from '../controllers/file'; const router = Router(); router.post('/upload', fileController.upload); -router.get('/download/:filePath(*)', fileController.download); +router.get('/download', fileController.download); export default router; From 55a87c53194613bd44ecb6ced3d7f06a1ad2bce2 Mon Sep 17 00:00:00 2001 From: Tem Taepaisitphongse Date: Fri, 17 Sep 2021 12:25:09 -0400 Subject: [PATCH 02/11] update: return upload as promise --- src/controllers/file.ts | 2 +- src/middlewares/upload.ts | 24 +++++++++++++++++------- 2 files changed, 18 insertions(+), 8 deletions(-) diff --git a/src/controllers/file.ts b/src/controllers/file.ts index 6bfacce..6360d21 100644 --- a/src/controllers/file.ts +++ b/src/controllers/file.ts @@ -18,7 +18,7 @@ export default { }, download: async (req: Request, res: Response) => { try { - const filePath = 'ml/filename'; + const filePath = ''; await download(filePath, req, res); } catch (err) { diff --git a/src/middlewares/upload.ts b/src/middlewares/upload.ts index 42574a6..37dd18c 100644 --- a/src/middlewares/upload.ts +++ b/src/middlewares/upload.ts @@ -2,7 +2,9 @@ import path from 'path'; import FileType from 'file-type'; import s3 from '../config/s3'; -const upload = async (buffer: any, filePath: string, fileName: string) => { +const upload = async (base64: any, filePath: string, fileName: string) => { + const buffer = Buffer.from(base64, 'base64'); + const { ext, mime } = (await FileType.fromBuffer(buffer)) || { ext: 'unknown', mime: 'unknown', @@ -16,11 +18,19 @@ const upload = async (buffer: any, filePath: string, fileName: string) => { Body: buffer, }; - s3.putObject(params, function(err) { - if (err) console.log(err); - }); - - return { url: `s3://app4stroke/${fullPath}`, gsutilURI: `https://app4stroke.s3.ap-southeast-1.amazonaws.com/${fullPath}` }; + return new Promise((resolve, reject) => { + s3.putObject(params) + .promise() + .then(() => { + resolve({ + url: `s3://app4stroke/${fullPath}`, + gsutilURI: `https://app4stroke.s3.ap-southeast-1.amazonaws.com/${fullPath}`, + }); + }) + .catch(() => { + reject({}); + }); + }) }; -export default upload; +export default upload; \ No newline at end of file From 35e0f1876d5f30c0839bb5345277189d295a2e1f Mon Sep 17 00:00:00 2001 From: Tem Taepaisitphongse Date: Fri, 17 Sep 2021 12:26:35 -0400 Subject: [PATCH 03/11] remove base64 --- src/middlewares/upload.ts | 4 +--- 1 file changed, 1 insertion(+), 3 deletions(-) diff --git a/src/middlewares/upload.ts b/src/middlewares/upload.ts index 37dd18c..849f39e 100644 --- a/src/middlewares/upload.ts +++ b/src/middlewares/upload.ts @@ -2,9 +2,7 @@ import path from 'path'; import FileType from 'file-type'; import s3 from '../config/s3'; -const upload = async (base64: any, filePath: string, fileName: string) => { - const buffer = Buffer.from(base64, 'base64'); - +const upload = async (buffer: any, filePath: string, fileName: string) => { const { ext, mime } = (await FileType.fromBuffer(buffer)) || { ext: 'unknown', mime: 'unknown', From 4fb10d0b5db3957355c5493a4133e2e6bb31acc9 Mon Sep 17 00:00:00 2001 From: yokeTH Date: Thu, 7 Oct 2021 22:04:55 +0700 Subject: [PATCH 04/11] storage Obj --- src/config/cloudStorage.ts | 212 ++++++++++++++++++++++++++++++ src/config/{storage.ts => gcp.ts} | 0 src/middlewares/delete.ts | 29 ++++ src/middlewares/fileService.ts | 0 src/middlewares/upload.ts | 25 +++- 5 files changed, 259 insertions(+), 7 deletions(-) create mode 100644 src/config/cloudStorage.ts rename src/config/{storage.ts => gcp.ts} (100%) create mode 100644 src/middlewares/delete.ts create mode 100644 src/middlewares/fileService.ts diff --git a/src/config/cloudStorage.ts b/src/config/cloudStorage.ts new file mode 100644 index 0000000..15fa09a --- /dev/null +++ b/src/config/cloudStorage.ts @@ -0,0 +1,212 @@ +import path from 'path'; +import FileType from 'file-type'; + +export interface uploadResponse { + success: Boolean; + uri?: string; + url?: string; + path?: string; +} + +export interface deleteResponse { + success: Boolean; +} + +export interface storage { + upload( + buffer: Buffer, + location: string, + fileName: string, + ): Promise; + download(path: string): Promise; + delete(path: string): Promise; +} + +// +// +// | ==================== | +// | AWS S3 Storage | +// | ==================== | +// +// +import AWS from 'aws-sdk'; + +class S3storage implements storage { + accessKeyId: string; + secretAccessKey: string; + region: string; + bucket: string; + s3: AWS.S3; + + constructor( + accessKeyId: string, + secretAccessKey: string, + region: string, + bucket: string, + ) { + this.accessKeyId = accessKeyId; + this.secretAccessKey = secretAccessKey; + this.region = region; + this.bucket = bucket; + this.s3 = new AWS.S3({ + accessKeyId: accessKeyId, + secretAccessKey: secretAccessKey, + region: region, + }); + } + + async upload( + buffer: Buffer, + location: string, + fileName: string, + ): Promise { + let { ext } = (await FileType.fromBuffer(buffer)) || { + ext: 'unknown', + }; + + let fullPath = path.join(location, fileName + '.' + ext); + + let params = { + Bucket: this.bucket, + Key: fullPath, + Body: buffer, + }; + + return new Promise((resolve, reject) => { + this.s3.putObject(params, async (err: Error, data: Object) => { + if (err) { + resolve({ + success: true, + uri: `s3://${this.bucket}/${fullPath}`, + url: `https://${this.bucket}.s3.${this.region}.amazonaws.com/${fullPath}`, + path: fullPath, + }); + } else { + reject({ + success: false, + }); + } + }); + }); + } + + async download(path: string): Promise { + let params = { + Bucket: this.bucket, + Key: path, + }; + return new Promise((resolve, reject) => { + this.s3.getObject(params, async (err: Error, data: Object) => { + if (err) { + reject(err); + } else { + resolve(data); + } + }); + }); + } + + async delete(path: string): Promise { + let params = { + Bucket: this.bucket, + Key: path, + }; + return new Promise((resolve, reject) => { + this.s3.deleteObject(params, async (err: Error, data: Object) => { + if (err) { + reject({ + success: false, + }); + } else { + resolve({ + success: true, + }); + } + }); + }); + } +} + +// +// +// | ==================== | +// | Google Cloud Storage | +// | ==================== | +// +// +import { Bucket, Storage } from '@google-cloud/storage'; + +class googleStorage implements storage { + keyFilename: string; + bucket: Bucket; + + constructor(keyFilename: string, bucket: string) { + this.keyFilename = keyFilename; + this.bucket = new Storage({ keyFilename: 'google-cloud-key.json' }).bucket( + bucket, + ); + } + + async upload( + buffer: Buffer, + location: string, + fileName: string, + ): Promise { + let { ext } = (await FileType.fromBuffer(buffer)) || { + ext: 'unknown', + }; + + let fullPath = path.join(location, fileName + '.' + ext); + let file = this.bucket.file(fullPath); + + return new Promise((resolve, reject) => { + file.save(buffer, async (err) => { + if (err) { + resolve({ + success: true, + uri: `gs://${this.bucket.name}/${fullPath}`, + url: `https://storage.cloud.google.com/${this.bucket.name}/${fullPath}`, + path: fullPath, + }); + } else { + reject({ + success: false, + }); + } + }); + }); + } + + async download(path: string): Promise { + let file = this.bucket.file(path); + return new Promise((resolve, reject) => { + file.getMetadata(async (err: Error, metadata: Object) => { + if (err) { + reject(err); + } else { + resolve(metadata); + } + }); + }); + } + + async delete(path: string): Promise { + let file = this.bucket.file(path); + + return new Promise((resolve, reject) => { + file.delete(async (err: Error) => { + if (err) { + reject({ + success: false, + }); + } else { + resolve({ + success: true, + }); + } + }); + }); + } +} + +export { S3storage, googleStorage }; diff --git a/src/config/storage.ts b/src/config/gcp.ts similarity index 100% rename from src/config/storage.ts rename to src/config/gcp.ts diff --git a/src/middlewares/delete.ts b/src/middlewares/delete.ts new file mode 100644 index 0000000..d9fab68 --- /dev/null +++ b/src/middlewares/delete.ts @@ -0,0 +1,29 @@ +import s3 from '../config/s3'; + +export interface deleteResponse { + success: Boolean; +} + +const del = async (buffer: Buffer, filePath: string) => { + var params = { + Bucket: 'app4stroke', + Key: filePath, + }; + + return new Promise((resolve, reject) => { + s3.deleteObject(params) + .promise() + .then(() => { + resolve({ + success: true, + }); + }) + .catch(() => { + reject({ + success: false, + }); + }); + }); +}; + +export default del; diff --git a/src/middlewares/fileService.ts b/src/middlewares/fileService.ts new file mode 100644 index 0000000..e69de29 diff --git a/src/middlewares/upload.ts b/src/middlewares/upload.ts index 849f39e..426884b 100644 --- a/src/middlewares/upload.ts +++ b/src/middlewares/upload.ts @@ -2,6 +2,13 @@ import path from 'path'; import FileType from 'file-type'; import s3 from '../config/s3'; +export interface uploadResponse { + success: Boolean; + uri?: string; + url?: string; + path?: string; +} + const upload = async (buffer: any, filePath: string, fileName: string) => { const { ext, mime } = (await FileType.fromBuffer(buffer)) || { ext: 'unknown', @@ -11,24 +18,28 @@ const upload = async (buffer: any, filePath: string, fileName: string) => { const fullPath = path.join(filePath, fileName + '.' + ext); var params = { - Bucket: "app4stroke", + Bucket: 'app4stroke', Key: fullPath, Body: buffer, }; - return new Promise((resolve, reject) => { + return new Promise((resolve, reject) => { s3.putObject(params) .promise() .then(() => { resolve({ - url: `s3://app4stroke/${fullPath}`, - gsutilURI: `https://app4stroke.s3.ap-southeast-1.amazonaws.com/${fullPath}`, + success: true, + uri: `s3://app4stroke/${fullPath}`, + url: `https://app4stroke.s3.ap-southeast-1.amazonaws.com/${fullPath}`, + path: fullPath, }); }) .catch(() => { - reject({}); + reject({ + success: false, + }); }); - }) + }); }; -export default upload; \ No newline at end of file +export default upload; From 58ea076883eb464fbc63f174e9cf9e4962be7b48 Mon Sep 17 00:00:00 2001 From: yokeTH Date: Thu, 7 Oct 2021 22:14:11 +0700 Subject: [PATCH 05/11] config storage --- src/config/storage.ts | 2 ++ 1 file changed, 2 insertions(+) create mode 100644 src/config/storage.ts diff --git a/src/config/storage.ts b/src/config/storage.ts new file mode 100644 index 0000000..cfe3897 --- /dev/null +++ b/src/config/storage.ts @@ -0,0 +1,2 @@ +import { googleStorage } from './cloudStorage'; +export default new googleStorage('google-cloud-key.json', 'stroke_images_3'); From 75c26d2c9d9c3296986c7816d67fee216c4ef902 Mon Sep 17 00:00:00 2001 From: yokeTH Date: Fri, 8 Oct 2021 00:56:24 +0700 Subject: [PATCH 06/11] fix bug; check dl() type --- src/config/cloudStorage.ts | 44 ++++++++++++++++++++++---------------- 1 file changed, 25 insertions(+), 19 deletions(-) diff --git a/src/config/cloudStorage.ts b/src/config/cloudStorage.ts index 15fa09a..e909de6 100644 --- a/src/config/cloudStorage.ts +++ b/src/config/cloudStorage.ts @@ -60,8 +60,9 @@ class S3storage implements storage { location: string, fileName: string, ): Promise { - let { ext } = (await FileType.fromBuffer(buffer)) || { + let { ext, mime } = (await FileType.fromBuffer(buffer)) || { ext: 'unknown', + mime: 'unknown', }; let fullPath = path.join(location, fileName + '.' + ext); @@ -70,39 +71,43 @@ class S3storage implements storage { Bucket: this.bucket, Key: fullPath, Body: buffer, + ContentType: mime.toString(), }; return new Promise((resolve, reject) => { - this.s3.putObject(params, async (err: Error, data: Object) => { + this.s3.putObject(params, async (err: AWS.AWSError) => { if (err) { + reject({ + success: false, + }); + } else { resolve({ success: true, uri: `s3://${this.bucket}/${fullPath}`, url: `https://${this.bucket}.s3.${this.region}.amazonaws.com/${fullPath}`, path: fullPath, }); - } else { - reject({ - success: false, - }); } }); }); } - async download(path: string): Promise { + async download(path: string): Promise { let params = { Bucket: this.bucket, Key: path, }; return new Promise((resolve, reject) => { - this.s3.getObject(params, async (err: Error, data: Object) => { - if (err) { - reject(err); - } else { - resolve(data); - } - }); + this.s3.getObject( + params, + async (err: AWS.AWSError, data: AWS.S3.GetObjectOutput) => { + if (err) { + reject(err); + } else { + resolve(data); + } + }, + ); }); } @@ -152,8 +157,9 @@ class googleStorage implements storage { location: string, fileName: string, ): Promise { - let { ext } = (await FileType.fromBuffer(buffer)) || { + let { ext, mime } = (await FileType.fromBuffer(buffer)) || { ext: 'unknown', + mime: 'unknown', }; let fullPath = path.join(location, fileName + '.' + ext); @@ -162,16 +168,16 @@ class googleStorage implements storage { return new Promise((resolve, reject) => { file.save(buffer, async (err) => { if (err) { + reject({ + success: false, + }); + } else { resolve({ success: true, uri: `gs://${this.bucket.name}/${fullPath}`, url: `https://storage.cloud.google.com/${this.bucket.name}/${fullPath}`, path: fullPath, }); - } else { - reject({ - success: false, - }); } }); }); From 82bea11ff1e4dd7f1f8f6b1c6facadccafa2a5eb Mon Sep 17 00:00:00 2001 From: yokeTH Date: Fri, 8 Oct 2021 00:56:51 +0700 Subject: [PATCH 07/11] change to S3 --- src/config/storage.ts | 13 +++++++++++-- 1 file changed, 11 insertions(+), 2 deletions(-) diff --git a/src/config/storage.ts b/src/config/storage.ts index cfe3897..e5490c8 100644 --- a/src/config/storage.ts +++ b/src/config/storage.ts @@ -1,2 +1,11 @@ -import { googleStorage } from './cloudStorage'; -export default new googleStorage('google-cloud-key.json', 'stroke_images_3'); +import { S3storage } from './cloudStorage'; +import dotenv from 'dotenv'; + +dotenv.config(); + +export default new S3storage( + process.env.AWS_ACCESS_KEY_ID || '', + process.env.AWS_SECRET_ACCESS_KEY || '', + process.env.AWS_DEFAULT_REGION || '', + process.env.AWS_BUCKET_NAME || '', +); From d53eaba6398910da8dee07ce1a5a0ae858b7c78e Mon Sep 17 00:00:00 2001 From: yokeTH Date: Fri, 8 Oct 2021 00:57:07 +0700 Subject: [PATCH 08/11] prototype Download --- src/controllers/file.ts | 28 ++++++++++++++++++++-------- src/routes/file.ts | 2 +- 2 files changed, 21 insertions(+), 9 deletions(-) diff --git a/src/controllers/file.ts b/src/controllers/file.ts index 6360d21..2ca594e 100644 --- a/src/controllers/file.ts +++ b/src/controllers/file.ts @@ -3,6 +3,7 @@ import httpError from '../errorHandler/httpError/httpError'; import upload from '../middlewares/upload'; import download from '../middlewares/download'; +import storage from '../config/storage'; export default { upload: async (req: Request, res: Response) => { @@ -17,14 +18,25 @@ export default { } }, download: async (req: Request, res: Response) => { - try { - const filePath = ''; + // try { + // const filePath = ''; - await download(filePath, req, res); - } catch (err) { - res - .status(500) - .send(httpError(500, 'Could not download the file. ' + err)); - } + // await download(filePath, req, res); + // } catch (err) { + // res + // .status(500) + // .send(httpError(500, 'Could not download the file. ' + err)); + // } + try { + const dl = await storage.download(req.params.path); + if (dl instanceof Error) { + throw new Error(); + } + if (!(typeof dl.ContentType === 'string')) { + throw new Error(); + } + res.setHeader('Content-Type', dl.ContentType); + res.send(dl.Body); + } catch (error: any) {} }, }; diff --git a/src/routes/file.ts b/src/routes/file.ts index 1c1bc91..7c3e29b 100644 --- a/src/routes/file.ts +++ b/src/routes/file.ts @@ -4,6 +4,6 @@ import fileController from '../controllers/file'; const router = Router(); router.post('/upload', fileController.upload); -router.get('/download', fileController.download); +router.get('/download/:path(*)', fileController.download); export default router; From 44ee879a3a7759237c41a05636ffad76d072f9bb Mon Sep 17 00:00:00 2001 From: yokeTH Date: Sat, 9 Oct 2021 19:14:14 +0700 Subject: [PATCH 09/11] listFiles --- src/config/cloudStorage.ts | 42 ++++++++++++++++++++++++++++++++++++++ 1 file changed, 42 insertions(+) diff --git a/src/config/cloudStorage.ts b/src/config/cloudStorage.ts index e909de6..c3cbcc9 100644 --- a/src/config/cloudStorage.ts +++ b/src/config/cloudStorage.ts @@ -20,6 +20,8 @@ export interface storage { ): Promise; download(path: string): Promise; delete(path: string): Promise; + listFiles(prefixPath: string): Promise>; + deletes(directory: string): Promise; } // @@ -55,6 +57,11 @@ class S3storage implements storage { }); } + // FIX: + deletes(directory: string): Promise { + throw new Error('Method not implemented.'); + } + async upload( buffer: Buffer, location: string, @@ -130,6 +137,24 @@ class S3storage implements storage { }); }); } + + listFiles(prefixPath: string): Promise> { + let params = { + Bucket: this.bucket, + Prefix: prefixPath, + }; + return new Promise((resolve, reject) => { + this.s3.listObjectsV2(params, async (err, files) => { + if (err) { + reject({}); + } else { + if (files.Contents) { + resolve(files.Contents.map((ele) => ele.Key)); + } + } + }); + }); + } } // @@ -152,6 +177,11 @@ class googleStorage implements storage { ); } + // FIX: + deletes(directory: string): Promise { + throw new Error('Method not implemented.'); + } + async upload( buffer: Buffer, location: string, @@ -213,6 +243,18 @@ class googleStorage implements storage { }); }); } + + async listFiles(prefixPath: string): Promise> { + return new Promise((resolve, reject) => { + this.bucket.getFiles({ prefix: prefixPath }, async (err, files: any) => { + if (err) { + reject({}); + } else { + resolve(files.map((ele: any) => ele.name)); + } + }); + }); + } } export { S3storage, googleStorage }; From 38543af67da5a353c793898973ca8f17d6e394fe Mon Sep 17 00:00:00 2001 From: yokeTH Date: Sat, 9 Oct 2021 19:52:12 +0700 Subject: [PATCH 10/11] method deletes --- src/config/cloudStorage.ts | 53 +++++++++++++++++++++++++++++++++----- 1 file changed, 46 insertions(+), 7 deletions(-) diff --git a/src/config/cloudStorage.ts b/src/config/cloudStorage.ts index c3cbcc9..abe06d9 100644 --- a/src/config/cloudStorage.ts +++ b/src/config/cloudStorage.ts @@ -57,9 +57,31 @@ class S3storage implements storage { }); } - // FIX: - deletes(directory: string): Promise { - throw new Error('Method not implemented.'); + async deletes(directory: string): Promise { + if (!directory.endsWith('/')) directory += '/'; + + let params: AWS.S3.DeleteObjectsRequest = { + Bucket: this.bucket, + Delete: { Objects: [] }, + }; + + (await this.listFiles(directory)).forEach((ele) => { + if (ele) params.Delete.Objects.push({ Key: ele }); + }); + + return new Promise((resolve, reject) => { + this.s3.deleteObjects(params, async (err: Error, data: Object) => { + if (err) { + reject({ + success: false, + }); + } else { + resolve({ + success: true, + }); + } + }); + }); } async upload( @@ -138,7 +160,9 @@ class S3storage implements storage { }); } - listFiles(prefixPath: string): Promise> { + async listFiles(prefixPath: string): Promise> { + if (!prefixPath.endsWith('/')) prefixPath += '/'; + let params = { Bucket: this.bucket, Prefix: prefixPath, @@ -164,7 +188,7 @@ class S3storage implements storage { // | ==================== | // // -import { Bucket, Storage } from '@google-cloud/storage'; +import { Bucket, DeleteFilesOptions, Storage } from '@google-cloud/storage'; class googleStorage implements storage { keyFilename: string; @@ -177,9 +201,22 @@ class googleStorage implements storage { ); } - // FIX: deletes(directory: string): Promise { - throw new Error('Method not implemented.'); + if (!directory.endsWith('/')) directory += '/'; + return new Promise((resolve, reject) => { + let params: DeleteFilesOptions = { prefix: directory }; + this.bucket.deleteFiles(params, async (err) => { + if (err) { + reject({ + success: false, + }); + } else { + resolve({ + success: true, + }); + } + }); + }); } async upload( @@ -245,6 +282,8 @@ class googleStorage implements storage { } async listFiles(prefixPath: string): Promise> { + if (!prefixPath.endsWith('/')) prefixPath += '/'; + return new Promise((resolve, reject) => { this.bucket.getFiles({ prefix: prefixPath }, async (err, files: any) => { if (err) { From cfeda04a72c80ee0bc261bee263ebf318cfa9fa6 Mon Sep 17 00:00:00 2001 From: yokeTH Date: Sat, 9 Oct 2021 19:54:49 +0700 Subject: [PATCH 11/11] comment GCP --- src/config/storage.ts | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/src/config/storage.ts b/src/config/storage.ts index e5490c8..e50d415 100644 --- a/src/config/storage.ts +++ b/src/config/storage.ts @@ -1,4 +1,4 @@ -import { S3storage } from './cloudStorage'; +import { S3storage, googleStorage } from './cloudStorage'; import dotenv from 'dotenv'; dotenv.config(); @@ -9,3 +9,4 @@ export default new S3storage( process.env.AWS_DEFAULT_REGION || '', process.env.AWS_BUCKET_NAME || '', ); +// export default new googleStorage('google-cloud-key.json', 'stroke_images_3');