在浏览器中直接对S3 URI进行GET时,如何从AWS读取二进制数据响应?



一般情况:这是一个使用MERN堆栈的应用程序,但问题更具体到AWS S3数据。

我有一个S3设置,我存储图像和文件从我的应用程序那里。我通常使用服务器生成signedurl,然后从浏览器直接上传。

在我的应用程序数据库中,我将对象uri存储为字符串,然后是图像,例如我可以用<img/>标记渲染,没有问题。到目前为止一切顺利。

但是,当它们是PDF并且我想让用户下载我存储在S3中的PDF时,执行<a href={s3Uri} download>只会导致PDF在另一个窗口/选项卡中打开,而不是提示用户下载。我相信这是由于下载属性依赖于同源,你不能从外部资源下载文件(如果我错了请纠正我)

然后我的下一个尝试是使用axios直接从http获取资源,它看起来像这样

axios.create({
baseURL: attachment.fileUrl,
headers: {common: {Authorization: ''}}
})
.get('')
.then(res => {
console.log(res)
console.log(typeof res.data)
console.log(new Buffer.from(res.data).toString())
})

所以通过这样做,我成功地读取响应头(有用的,因为然后我可以处理图像/文件不同),但是当我尝试读取二进制数据返回我已经不成功,并解析它,甚至确定它是如何编码,它看起来像这样

%PDF-1.3
3 0 obj
<</Type /Page
/Parent 1 0 R
/Resources 2 0 R
/Contents 4 0 R>>
endobj
4 0 obj
<</Filter /FlateDecode /Length 1811>>
stream
x�X�R�=k=E׷�������Na˅��/���� �[�]��.�,��^ �wF0�.��Ie�0�o��ݧO_IoG����p��4�BJI���g��d|��H�$�12(R*oB��:%먺�����:�R�Ф6�Xɔ�[:�[��h�(�MQ���>���;l[[��VN�hK/][�!�mJC
.... and so on

我有另一个函数,我用它来允许用户下载pdf,我直接存储在我的数据库中的base64字符串。这些是我的应用程序生成的PDF文件,相当小,所以我直接将它们存储在数据库中,而不是存储在AWS S3中的用户提交的文件,大小可以是几mb(我的数据库中的文件只有几KB)

我用来处理base64 pdf文件并向用户提供可下载链接的函数如下所示

export const makePdfUrlFromBase64 = (base64) => {
const binaryImg = atob(base64);
const binaryImgLength = binaryImg.length;
const arrayBuffer = new ArrayBuffer(binaryImgLength);
const uInt8Array = new Uint8Array(arrayBuffer);
for (let i = 0;  i < binaryImgLength;  i++) {
uInt8Array[i] = binaryImg.charCodeAt(i);
}
const outputBlob = new Blob([uInt8Array], {type: 'application/pdf'});
return URL.createObjectURL(outputBlob)
}

然而,当我尝试将此函数应用于从AWS返回的数据时,我得到这个错误:

DOMException: Failed to execute 'atob' on 'Window': The string to be decoded contains characters outside of the Latin1 range.

那么我这里从AWS得到的二进制数据编码是什么呢?

注意:我可以通过在img标签中传递src来渲染这个二进制数据的图像,像这样:<img src={数据:$ {res.headers("内容类型")};base64, $ {res。data}} />

这是我最大的暗示,这是某种形式的base64?

请!如果有人能告诉我如何实现我的目标,我洗耳恭听!目标是能够提示用户下载我在S3 URI中的资源。我可以链接到它,他们可以在浏览器中打开它,然后手动下载,但我想强制提示。

有人知道这里返回的是什么类型的数据吗?有什么方法来解析它作为一个流吗?一个缓冲区?我已经尝试用JSON将其字符串化或将其作为字符串记录到控制台,在这一点上我愿意接受所有建议

您正在进行各种不必要的转换。当您执行GET请求时,您已经拥有所需格式的数据。

const response = await fetch(attachment.fileUrl,
headers: {Authorization: ''}}
});
const blob = await response.blob();
return URL.createObjectURL(res.data);

最新更新