Skip to content

Commit 1a4ef1f

Browse files
committed
feat(storage/s3): use @aws-sdk/lib-storage for uploads
1 parent 1fbf884 commit 1a4ef1f

File tree

4 files changed

+269
-300
lines changed

4 files changed

+269
-300
lines changed

lib/storage/drivers/s3.ts

Lines changed: 20 additions & 12 deletions
Original file line numberDiff line numberDiff line change
@@ -6,15 +6,15 @@ import {
66
GetObjectCommand,
77
HeadBucketCommand,
88
ListObjectsV2Command,
9-
PutObjectCommand,
109
S3Client,
1110
} from '@aws-sdk/client-s3'
12-
import { getSignedUrl } from '@aws-sdk/s3-request-presigner'
11+
import { Upload } from '@aws-sdk/lib-storage'
1312

13+
import { getSignedUrl } from '@aws-sdk/s3-request-presigner'
1414
import * as R from 'remeda'
1515
import { z } from 'zod'
1616
import { parseEnv, StorageDriver } from '~/lib/storage/defineStorageDriver'
17-
import { createTempDir, streamToBuffer } from '~/lib/utils'
17+
import { createTempDir } from '~/lib/utils'
1818

1919
export class S3StorageDriver extends StorageDriver {
2020
s3
@@ -96,16 +96,20 @@ export class S3StorageDriver extends StorageDriver {
9696
}
9797

9898
async uploadPart(opts: { uploadId: string; partNumber: number; data: ReadableStream }) {
99-
await this.s3.send(
100-
new PutObjectCommand({
99+
const upload = new Upload({
100+
client: this.s3,
101+
params: {
101102
Bucket: this.bucket,
102103
Key: this.getUploadPartObjectName({
103104
uploadId: opts.uploadId,
104105
partNumber: opts.partNumber,
105106
}),
106-
Body: await streamToBuffer(opts.data),
107-
}),
108-
)
107+
Body: opts.data,
108+
},
109+
partSize: 64 * 1024 * 1024, // 64 MB
110+
queueSize: 1,
111+
})
112+
await upload.done()
109113
}
110114

111115
async completeMultipartUpload(opts: {
@@ -147,13 +151,17 @@ export class S3StorageDriver extends StorageDriver {
147151
await outputTempFile.close()
148152

149153
const readStream = createReadStream(outputTempFilePath)
150-
await this.s3.send(
151-
new PutObjectCommand({
154+
const upload = new Upload({
155+
client: this.s3,
156+
params: {
152157
Bucket: this.bucket,
153158
Key: this.addBaseFolderPrefix(opts.finalOutputObjectName),
154159
Body: readStream,
155-
}),
156-
)
160+
},
161+
partSize: 64 * 1024 * 1024, // 64 MB
162+
queueSize: 1,
163+
})
164+
await upload.done()
157165

158166
await Promise.all([
159167
this.cleanupMultipartUpload(opts.uploadId),

lib/utils.ts

Lines changed: 0 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -3,19 +3,6 @@ import { promises as fs } from 'node:fs'
33
import path from 'node:path'
44
import { ENV } from './env'
55

6-
export async function streamToBuffer(stream: ReadableStream<Uint8Array>): Promise<Buffer> {
7-
const reader = stream.getReader()
8-
const chunks: Uint8Array[] = []
9-
10-
while (true) {
11-
const { done, value } = await reader.read()
12-
if (done) break
13-
chunks.push(value)
14-
}
15-
16-
return Buffer.concat(chunks)
17-
}
18-
196
export function getObjectNameFromKey(key: string, version: string) {
207
return hash('sha1', Buffer.from(`${key}-${version}`))
218
}

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -26,6 +26,7 @@
2626
"dependencies": {
2727
"@antfu/utils": "^9.2.0",
2828
"@aws-sdk/client-s3": "^3.740.0",
29+
"@aws-sdk/lib-storage": "^3.846.0",
2930
"@aws-sdk/s3-request-presigner": "^3.740.0",
3031
"@google-cloud/storage": "^7.15.0",
3132
"@types/better-sqlite3": "^7.6.12",

0 commit comments

Comments
 (0)