pg-mvc-service 2.0.9 → 2.0.11
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
|
@@ -15,12 +15,17 @@ var __asyncValues = (this && this.__asyncValues) || function (o) {
|
|
|
15
15
|
function verb(n) { i[n] = o[n] && function (v) { return new Promise(function (resolve, reject) { v = o[n](v), settle(resolve, reject, v.done, v.value); }); }; }
|
|
16
16
|
function settle(resolve, reject, d, v) { Promise.resolve(v).then(function(v) { resolve({ value: v, done: d }); }, reject); }
|
|
17
17
|
};
|
|
18
|
+
var __importDefault = (this && this.__importDefault) || function (mod) {
|
|
19
|
+
return (mod && mod.__esModule) ? mod : { "default": mod };
|
|
20
|
+
};
|
|
18
21
|
Object.defineProperty(exports, "__esModule", { value: true });
|
|
19
22
|
exports.AwsS3Client = void 0;
|
|
20
23
|
const client_s3_1 = require("@aws-sdk/client-s3");
|
|
21
24
|
const Base64Client_1 = require("./Base64Client");
|
|
25
|
+
const Exception_1 = require("../exceptions/Exception");
|
|
26
|
+
const axios_1 = __importDefault(require("axios"));
|
|
22
27
|
class AwsS3Client {
|
|
23
|
-
get
|
|
28
|
+
get UrlPrefix() {
|
|
24
29
|
return `https://${this.bucketName}.s3.${this.region}.amazonaws.com`;
|
|
25
30
|
}
|
|
26
31
|
constructor(params) {
|
|
@@ -55,7 +60,7 @@ class AwsS3Client {
|
|
|
55
60
|
}
|
|
56
61
|
url(path, fileName = '') {
|
|
57
62
|
path = path.replace(/^\/|\/$/g, '');
|
|
58
|
-
let url = `${this.
|
|
63
|
+
let url = `${this.UrlPrefix}`;
|
|
59
64
|
if (path !== '') {
|
|
60
65
|
url += '/' + path;
|
|
61
66
|
}
|
|
@@ -122,7 +127,45 @@ class AwsS3Client {
|
|
|
122
127
|
ContentType: type
|
|
123
128
|
});
|
|
124
129
|
yield this.client.send(command);
|
|
125
|
-
return `${this.
|
|
130
|
+
return `${this.UrlPrefix}/${key}`;
|
|
131
|
+
});
|
|
132
|
+
}
|
|
133
|
+
uploadFromUrl(path, fileName, url) {
|
|
134
|
+
return __awaiter(this, void 0, void 0, function* () {
|
|
135
|
+
try {
|
|
136
|
+
// URLからデータを取得
|
|
137
|
+
const response = yield axios_1.default.get(url, {
|
|
138
|
+
responseType: 'arraybuffer',
|
|
139
|
+
timeout: 30000,
|
|
140
|
+
});
|
|
141
|
+
// Content-Typeを取得
|
|
142
|
+
const contentType = response.headers['content-type'] || 'application/octet-stream';
|
|
143
|
+
const key = this.makeKey(path, fileName);
|
|
144
|
+
const command = new client_s3_1.PutObjectCommand({
|
|
145
|
+
Bucket: this.bucketName,
|
|
146
|
+
Key: key,
|
|
147
|
+
Body: Buffer.from(response.data),
|
|
148
|
+
ContentType: contentType,
|
|
149
|
+
ContentLength: response.data.length
|
|
150
|
+
});
|
|
151
|
+
yield this.client.send(command);
|
|
152
|
+
// アップロードされたファイルのURLを返す
|
|
153
|
+
return this.url(path, fileName);
|
|
154
|
+
}
|
|
155
|
+
catch (error) {
|
|
156
|
+
if (axios_1.default.isAxiosError(error)) {
|
|
157
|
+
if (error.response) {
|
|
158
|
+
throw new Exception_1.UnprocessableException(`Failed to download from URL. HTTP ${error.response.status}: ${error.response.statusText}`);
|
|
159
|
+
}
|
|
160
|
+
else if (error.request) {
|
|
161
|
+
throw new Exception_1.UnprocessableException('Failed to connect to the URL. Please check if the URL is accessible.');
|
|
162
|
+
}
|
|
163
|
+
else {
|
|
164
|
+
throw new Exception_1.UnprocessableException('Invalid URL format.');
|
|
165
|
+
}
|
|
166
|
+
}
|
|
167
|
+
throw new Exception_1.UnprocessableException('Failed to upload from URL.');
|
|
168
|
+
}
|
|
126
169
|
});
|
|
127
170
|
}
|
|
128
171
|
uploadStackText(path, fileName, text) {
|
|
@@ -265,5 +308,27 @@ class AwsS3Client {
|
|
|
265
308
|
}
|
|
266
309
|
});
|
|
267
310
|
}
|
|
311
|
+
deleteFromUrl(url_1) {
|
|
312
|
+
return __awaiter(this, arguments, void 0, function* (url, isFileUrl = true) {
|
|
313
|
+
const path = url.replace(this.UrlPrefix + '/', '');
|
|
314
|
+
if (url === path) {
|
|
315
|
+
throw new Exception_1.UnprocessableException('The specified URL cannot be deleted because the bucket and region do not match.');
|
|
316
|
+
}
|
|
317
|
+
if (path.trim() === "") {
|
|
318
|
+
throw new Exception_1.UnprocessableException('This URL is invalid.');
|
|
319
|
+
}
|
|
320
|
+
if (isFileUrl) {
|
|
321
|
+
const pathSplits = path.split('/');
|
|
322
|
+
const file = pathSplits.pop();
|
|
323
|
+
if (file === undefined) {
|
|
324
|
+
throw new Exception_1.UnprocessableException('This URL is invalid.');
|
|
325
|
+
}
|
|
326
|
+
yield this.deleteFile(pathSplits.join('/'), file);
|
|
327
|
+
}
|
|
328
|
+
else {
|
|
329
|
+
yield this.deleteDir(path);
|
|
330
|
+
}
|
|
331
|
+
});
|
|
332
|
+
}
|
|
268
333
|
}
|
|
269
334
|
exports.AwsS3Client = AwsS3Client;
|
|
@@ -224,10 +224,17 @@ class Base64Client {
|
|
|
224
224
|
if ('rate' in toSize) {
|
|
225
225
|
rate = toSize.rate;
|
|
226
226
|
}
|
|
227
|
-
else if ('w' in toSize && 'h' in toSize) {
|
|
227
|
+
else if ('w' in toSize && 'h' in toSize && 'func' in toSize) {
|
|
228
228
|
const wRate = toSize.w / width;
|
|
229
229
|
const hRate = toSize.h / height;
|
|
230
|
-
|
|
230
|
+
switch (toSize.func) {
|
|
231
|
+
case 'max':
|
|
232
|
+
rate = Math.max(wRate, hRate);
|
|
233
|
+
break;
|
|
234
|
+
case 'min':
|
|
235
|
+
rate = Math.min(wRate, hRate);
|
|
236
|
+
break;
|
|
237
|
+
}
|
|
231
238
|
}
|
|
232
239
|
else if ('w' in toSize) {
|
|
233
240
|
rate = toSize.w / width;
|
|
@@ -236,14 +243,16 @@ class Base64Client {
|
|
|
236
243
|
rate = toSize.h / height;
|
|
237
244
|
}
|
|
238
245
|
// 画像は1倍より大きくできないので
|
|
239
|
-
if (rate >= 1) {
|
|
246
|
+
if (rate >= 1 || rate <= 0) {
|
|
240
247
|
return base64Data;
|
|
241
248
|
}
|
|
242
249
|
let resizedImage;
|
|
243
250
|
// フォーマットに応じて処理を分岐
|
|
251
|
+
const targetWidth = Math.round(width * rate);
|
|
252
|
+
const targetHeight = Math.round(height * rate);
|
|
244
253
|
if (format === 'png') {
|
|
245
254
|
resizedImage = yield (0, sharp_1.default)(imageBuffer)
|
|
246
|
-
.resize(
|
|
255
|
+
.resize(targetWidth, targetHeight, {
|
|
247
256
|
fit: 'inside',
|
|
248
257
|
withoutEnlargement: true
|
|
249
258
|
})
|
|
@@ -253,7 +262,7 @@ class Base64Client {
|
|
|
253
262
|
else {
|
|
254
263
|
// JPEG、その他のフォーマット
|
|
255
264
|
resizedImage = yield (0, sharp_1.default)(imageBuffer)
|
|
256
|
-
.resize(
|
|
265
|
+
.resize(targetWidth, targetHeight, {
|
|
257
266
|
fit: 'inside',
|
|
258
267
|
withoutEnlargement: true
|
|
259
268
|
})
|
package/package.json
CHANGED
|
@@ -1,12 +1,14 @@
|
|
|
1
1
|
import { _Object, DeleteObjectsCommand, GetObjectCommand, ListObjectsV2Command, PutObjectCommand, S3Client, ScanRange } from '@aws-sdk/client-s3';
|
|
2
2
|
import { Base64Client } from './Base64Client';
|
|
3
|
+
import { UnprocessableException } from '../exceptions/Exception';
|
|
4
|
+
import axios from 'axios';
|
|
3
5
|
|
|
4
6
|
export class AwsS3Client {
|
|
5
7
|
private client: S3Client;
|
|
6
8
|
|
|
7
9
|
private readonly bucketName;
|
|
8
10
|
private readonly region;
|
|
9
|
-
get
|
|
11
|
+
get UrlPrefix(): string {
|
|
10
12
|
return `https://${this.bucketName}.s3.${this.region}.amazonaws.com`;
|
|
11
13
|
}
|
|
12
14
|
|
|
@@ -49,7 +51,7 @@ export class AwsS3Client {
|
|
|
49
51
|
|
|
50
52
|
public url(path: string, fileName: string = '') {
|
|
51
53
|
path = path.replace(/^\/|\/$/g, '');
|
|
52
|
-
let url = `${this.
|
|
54
|
+
let url = `${this.UrlPrefix}`;
|
|
53
55
|
if (path !== '') {
|
|
54
56
|
url += '/' + path;
|
|
55
57
|
}
|
|
@@ -118,7 +120,46 @@ export class AwsS3Client {
|
|
|
118
120
|
});
|
|
119
121
|
await this.client.send(command);
|
|
120
122
|
|
|
121
|
-
return `${this.
|
|
123
|
+
return `${this.UrlPrefix}/${key}`;
|
|
124
|
+
}
|
|
125
|
+
|
|
126
|
+
public async uploadFromUrl(path: string, fileName: string, url: string): Promise<string> {
|
|
127
|
+
try {
|
|
128
|
+
// URLからデータを取得
|
|
129
|
+
const response = await axios.get(url, {
|
|
130
|
+
responseType: 'arraybuffer',
|
|
131
|
+
timeout: 30000,
|
|
132
|
+
});
|
|
133
|
+
|
|
134
|
+
// Content-Typeを取得
|
|
135
|
+
const contentType = response.headers['content-type'] || 'application/octet-stream';
|
|
136
|
+
|
|
137
|
+
const key = this.makeKey(path, fileName);
|
|
138
|
+
const command = new PutObjectCommand({
|
|
139
|
+
Bucket: this.bucketName,
|
|
140
|
+
Key: key,
|
|
141
|
+
Body: Buffer.from(response.data),
|
|
142
|
+
ContentType: contentType,
|
|
143
|
+
ContentLength: response.data.length
|
|
144
|
+
});
|
|
145
|
+
|
|
146
|
+
await this.client.send(command);
|
|
147
|
+
|
|
148
|
+
// アップロードされたファイルのURLを返す
|
|
149
|
+
return this.url(path, fileName);
|
|
150
|
+
|
|
151
|
+
} catch (error) {
|
|
152
|
+
if (axios.isAxiosError(error)) {
|
|
153
|
+
if (error.response) {
|
|
154
|
+
throw new UnprocessableException(`Failed to download from URL. HTTP ${error.response.status}: ${error.response.statusText}`);
|
|
155
|
+
} else if (error.request) {
|
|
156
|
+
throw new UnprocessableException('Failed to connect to the URL. Please check if the URL is accessible.');
|
|
157
|
+
} else {
|
|
158
|
+
throw new UnprocessableException('Invalid URL format.');
|
|
159
|
+
}
|
|
160
|
+
}
|
|
161
|
+
throw new UnprocessableException('Failed to upload from URL.');
|
|
162
|
+
}
|
|
122
163
|
}
|
|
123
164
|
|
|
124
165
|
public async uploadStackText(path: string, fileName: string, text: string) {
|
|
@@ -234,4 +275,26 @@ export class AwsS3Client {
|
|
|
234
275
|
await this.client.send(deleteCommand);
|
|
235
276
|
}
|
|
236
277
|
}
|
|
278
|
+
|
|
279
|
+
public async deleteFromUrl(url: string, isFileUrl: boolean = true): Promise<void> {
|
|
280
|
+
const path = url.replace(this.UrlPrefix + '/', '');
|
|
281
|
+
if (url === path) {
|
|
282
|
+
throw new UnprocessableException('The specified URL cannot be deleted because the bucket and region do not match.');
|
|
283
|
+
}
|
|
284
|
+
|
|
285
|
+
if (path.trim() === "") {
|
|
286
|
+
throw new UnprocessableException('This URL is invalid.');
|
|
287
|
+
}
|
|
288
|
+
|
|
289
|
+
if (isFileUrl) {
|
|
290
|
+
const pathSplits = path.split('/');
|
|
291
|
+
const file = pathSplits.pop();
|
|
292
|
+
if (file === undefined) {
|
|
293
|
+
throw new UnprocessableException('This URL is invalid.');
|
|
294
|
+
}
|
|
295
|
+
await this.deleteFile(pathSplits.join('/'), file);
|
|
296
|
+
} else {
|
|
297
|
+
await this.deleteDir(path);
|
|
298
|
+
}
|
|
299
|
+
}
|
|
237
300
|
}
|
|
@@ -221,7 +221,7 @@ export class Base64Client {
|
|
|
221
221
|
return false;
|
|
222
222
|
}
|
|
223
223
|
|
|
224
|
-
public async resizeImage(base64Data: string, toSize: {w: number} | {h: number} | {w: number; h: number}| {rate: number}): Promise<string> {
|
|
224
|
+
public async resizeImage(base64Data: string, toSize: {w: number} | {h: number} | {w: number; h: number; func: 'max' | 'min'}| {rate: number}): Promise<string> {
|
|
225
225
|
if (ValidateStringUtil.isBase64(base64Data) === false) {
|
|
226
226
|
throw new Error("The specified data is not in base64 format");
|
|
227
227
|
}
|
|
@@ -236,10 +236,18 @@ export class Base64Client {
|
|
|
236
236
|
let rate = 1;
|
|
237
237
|
if ('rate' in toSize) {
|
|
238
238
|
rate = toSize.rate;
|
|
239
|
-
} else if ('w' in toSize && 'h' in toSize) {
|
|
239
|
+
} else if ('w' in toSize && 'h' in toSize && 'func' in toSize) {
|
|
240
240
|
const wRate = toSize.w / width;
|
|
241
241
|
const hRate = toSize.h / height;
|
|
242
|
-
|
|
242
|
+
switch (toSize.func) {
|
|
243
|
+
case 'max':
|
|
244
|
+
rate = Math.max(wRate, hRate);
|
|
245
|
+
break;
|
|
246
|
+
case 'min':
|
|
247
|
+
rate = Math.min(wRate, hRate);
|
|
248
|
+
break;
|
|
249
|
+
}
|
|
250
|
+
|
|
243
251
|
} else if ('w' in toSize) {
|
|
244
252
|
rate = toSize.w / width;
|
|
245
253
|
} else if ('h' in toSize) {
|
|
@@ -247,16 +255,18 @@ export class Base64Client {
|
|
|
247
255
|
}
|
|
248
256
|
|
|
249
257
|
// 画像は1倍より大きくできないので
|
|
250
|
-
if (rate >= 1) {
|
|
258
|
+
if (rate >= 1 || rate <= 0) {
|
|
251
259
|
return base64Data;
|
|
252
260
|
}
|
|
253
261
|
|
|
254
262
|
let resizedImage: Buffer;
|
|
255
263
|
|
|
256
264
|
// フォーマットに応じて処理を分岐
|
|
265
|
+
const targetWidth = Math.round(width * rate);
|
|
266
|
+
const targetHeight = Math.round(height * rate);
|
|
257
267
|
if (format === 'png') {
|
|
258
268
|
resizedImage = await sharp(imageBuffer)
|
|
259
|
-
.resize(
|
|
269
|
+
.resize(targetWidth, targetHeight, {
|
|
260
270
|
fit: 'inside',
|
|
261
271
|
withoutEnlargement: true
|
|
262
272
|
})
|
|
@@ -265,7 +275,7 @@ export class Base64Client {
|
|
|
265
275
|
} else {
|
|
266
276
|
// JPEG、その他のフォーマット
|
|
267
277
|
resizedImage = await sharp(imageBuffer)
|
|
268
|
-
.resize(
|
|
278
|
+
.resize(targetWidth, targetHeight, {
|
|
269
279
|
fit: 'inside',
|
|
270
280
|
withoutEnlargement: true
|
|
271
281
|
})
|