如何通过 client-side JavaScript 将任何类型的文件上传到 S3 存储桶?
How to upload any type of file to an S3 bucket via client-side JavaScript?
我在通过 FileReader
读取文件并通过 PutObject
将其正确上传到 S3 且文件未损坏时遇到问题。
问题描述
我一直在使用 MongoDB Stitch 作为我的应用程序的无服务器平台,它 built-in 带有 S3 服务提供商。我可以正确上传文本文件,但如果我尝试上传任何二进制文件(Excel、PDF、图像等)并直接从我的 S3 存储桶下载它并在其各自的程序中打开它,我的电脑会报告它已损坏。
我查看了两个文件,我电脑上的原始文件和上传到 S3 的文件,它们非常相似,但似乎在上传过程中更改了一些数据。
当前尝试
我正在使用 FileReader
打开阅读流并使用 FileReader.readAsBinaryString()
阅读文件。我在 headers 中的 ContentType
通过 File.type
.
我看到 W3C 建议使用 FileReader.readAsArrayBuffer()
而不是 readAsBinaryString()
,但是 S3 在尝试上传结果数据时报告错误:value for field "Body" should be of type "io.ReadSeeker"
.
我也试过 FileReader.readAsDataURL()
,但我不知道有什么方法可以将 any 文件类型的 base64 URL 转换回它的原始格式。我能找到的唯一例子都涉及使用 base64 到 encode/decode 图像。
代码
const readFile = (file) => {
return new Promise((resolve) => {
const fileReader = new FileReader()
fileReader.onload = (event) => {
resolve(event.target.result)
}
fileReader.readAsBinaryString(file)
})
}
async s3Upload(file) {
const fileData = await readFile(file)
const putObjectArgs = {
Body: fileData,
Key: file.name,
ContentType: file.type,
ACL: 'public-read',
Bucket: 'BUCKET_NAME',
}
// call the Stitch services to upload
}
问题
有没有办法将任何类型的文件上传到 S3,就像它存储在我的文件系统中一样?或 encode/decode 任何文件类型 to/from base64?
的通用方法
我找到了 FilePond 和类似的库,因为它支持任何类型的服务器上传,所以我决定使用它而不是尝试自己创建文件上传逻辑。
更新:
甚至 FilePond 都让您定义自己的 AWS 上传逻辑...但我终于想通了。
使用 MongoDB Stitch 时,您必须将 ArrayBuffer 转换为 UInt8Array,然后使用其 SDK 将其转换为 BSON 二进制类型。这是代码:
const reader = new FileReader()
reader.onload = (e) => {
const fileData = new Uint8Array(reader.result)
const fileBson = new BSON.Binary(fileData)
// upload to S3
// ...
}
reader.readAsArrayBuffer(file)
我在通过 FileReader
读取文件并通过 PutObject
将其正确上传到 S3 且文件未损坏时遇到问题。
问题描述
我一直在使用 MongoDB Stitch 作为我的应用程序的无服务器平台,它 built-in 带有 S3 服务提供商。我可以正确上传文本文件,但如果我尝试上传任何二进制文件(Excel、PDF、图像等)并直接从我的 S3 存储桶下载它并在其各自的程序中打开它,我的电脑会报告它已损坏。
我查看了两个文件,我电脑上的原始文件和上传到 S3 的文件,它们非常相似,但似乎在上传过程中更改了一些数据。
当前尝试
我正在使用 FileReader
打开阅读流并使用 FileReader.readAsBinaryString()
阅读文件。我在 headers 中的 ContentType
通过 File.type
.
我看到 W3C 建议使用 FileReader.readAsArrayBuffer()
而不是 readAsBinaryString()
,但是 S3 在尝试上传结果数据时报告错误:value for field "Body" should be of type "io.ReadSeeker"
.
我也试过 FileReader.readAsDataURL()
,但我不知道有什么方法可以将 any 文件类型的 base64 URL 转换回它的原始格式。我能找到的唯一例子都涉及使用 base64 到 encode/decode 图像。
代码
const readFile = (file) => {
return new Promise((resolve) => {
const fileReader = new FileReader()
fileReader.onload = (event) => {
resolve(event.target.result)
}
fileReader.readAsBinaryString(file)
})
}
async s3Upload(file) {
const fileData = await readFile(file)
const putObjectArgs = {
Body: fileData,
Key: file.name,
ContentType: file.type,
ACL: 'public-read',
Bucket: 'BUCKET_NAME',
}
// call the Stitch services to upload
}
问题
有没有办法将任何类型的文件上传到 S3,就像它存储在我的文件系统中一样?或 encode/decode 任何文件类型 to/from base64?
的通用方法我找到了 FilePond 和类似的库,因为它支持任何类型的服务器上传,所以我决定使用它而不是尝试自己创建文件上传逻辑。
更新:
甚至 FilePond 都让您定义自己的 AWS 上传逻辑...但我终于想通了。
使用 MongoDB Stitch 时,您必须将 ArrayBuffer 转换为 UInt8Array,然后使用其 SDK 将其转换为 BSON 二进制类型。这是代码:
const reader = new FileReader()
reader.onload = (e) => {
const fileData = new Uint8Array(reader.result)
const fileBson = new BSON.Binary(fileData)
// upload to S3
// ...
}
reader.readAsArrayBuffer(file)