-
-
Notifications
You must be signed in to change notification settings - Fork 0
/
s3upload.js
156 lines (130 loc) · 4.21 KB
/
s3upload.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
import { Upload } from '@aws-sdk/lib-storage';
import {HeadObjectCommand, S3} from '@aws-sdk/client-s3';
import { lookup } from 'mime-types';
import { PromisePool } from '@supercharge/promise-pool';
import path from 'path';
import fs from 'fs';
import {debugLog as debugLog_, hashFile, walk} from "./utils.js";
const debugLog = (...args) => debugLog_('S3', ...args);
const AWS_KEY_ID = process.env['AWS_KEY_ID'];
const SECRET_ACCESS_KEY = process.env['AWS_SECRET_ACCESS_KEY'];
const BUCKET = process.env['AWS_BUCKET'];
const ENDPOINT = process.env['AWS_ENDPOINT'];
const s3 = new S3({
credentials: {
accessKeyId: AWS_KEY_ID,
secretAccessKey: SECRET_ACCESS_KEY
},
region: 'auto',
endpoint: ENDPOINT
});
async function uploadS3Internal(params) {
await new Upload({
client: s3,
params
}).done();
}
async function _upload(data, cdnPath, contentType) {
debugLog('Upload', cdnPath, contentType);
const params = {
Bucket: BUCKET,
ACL: 'public-read',
Body: data,
Key: cdnPath,
ContentType: contentType,
};
try {
await uploadS3Internal(params);
return true;
}
catch(err) {
console.error('Failed to upload to S3', err);
return false;
}
}
async function uploadFile(filePath, cdnPath, attempt = 0) {
debugLog('Upload file', filePath, 'to', cdnPath, 'attempt', attempt);
try {
const size = (await fs.promises.stat(filePath)).size;
const contentType = lookup(filePath) || 'application/octet-stream';
if (await _upload(fs.createReadStream(filePath, {encoding: null}), cdnPath, contentType)) {
console.log(`Uploaded '${filePath}' to '${cdnPath}'`);
const head = await s3.send(new HeadObjectCommand({
Bucket: BUCKET,
Key: cdnPath
}));
if (+head.ContentLength === size) {
return true;
}
console.error(`Uploaded file size doesnt match. Local size: ${size}. Uploaded size: ${head.ContentLength}`)
}
console.error(`Error uploading '${filePath}' to '${cdnPath}'`);
} catch(e) {
console.error(e);
}
if (attempt < 3) {
return uploadFile(filePath, cdnPath, attempt + 1);
}
console.log('Failed to upload', filePath, 'to', cdnPath, 'after 3 attempts');
return false;
}
async function uploadDir(dirPath, cdnPath, version, sdkVersion) {
dirPath = path.resolve(dirPath);
debugLog('Upload dir', dirPath, 'to', cdnPath, version, sdkVersion);
const files = await walk(dirPath);
const hashes = { };
const sizes = { };
let result = true;
const uploadQueue = [];
console.log(files);
for (let i = 0; i < files.length; ++i) {
const file = files[i];
const stats = fs.statSync(file);
if (!stats.isDirectory()) {
const filePath = file.replace(dirPath, '').substring(1).replace(/\\/g, '/');
const key = (cdnPath.length > 0 ? (cdnPath + '/') : '') + filePath;
hashes[filePath] = await hashFile(file);
sizes[filePath] = stats.size;
uploadQueue.push({ file, key });
}
}
console.log(uploadQueue);
const { results, errors } = await PromisePool.for(uploadQueue).withConcurrency(10).process(async queueItem => {
return await uploadFile(queueItem.file, queueItem.key);
});
for (let i = 0; i < results.length; ++i) {
if (!results[i]) {
result = false;
}
}
if (version) {
debugLog('Generate update.json', version);
const updateData = JSON.stringify({
latestBuildNumber: -1,
version: version,
sdkVersion: sdkVersion || undefined,
hashList: hashes,
sizeList: sizes
});
if (!await _upload(updateData, cdnPath + '/update.json', 'application/json')) {
console.error(`Error uploading 'update.json' to key '${cdnPath}/update.json'`);
result = false;
} else {
console.log(`Uploaded 'update.json' to key '${cdnPath}/update.json'`);
}
}
return result;
}
export async function upload(filePath, cdnPath, version, sdkVersion) {
debugLog('Trying to upload', filePath, 'to', cdnPath, version, sdkVersion);
if (fs.existsSync(filePath)) {
if (fs.lstatSync(filePath).isDirectory()) {
return uploadDir(filePath, cdnPath, version, sdkVersion);
} else {
return uploadFile(filePath, cdnPath);
}
} else {
console.error('File not found');
return false;
}
}