在浏览器中直接对 S3 URI 执行 GET 时如何从 AWS 读取二进制数据响应?
How to read binary data response from AWS when doing a GET directly to an S3 URI in browser?
一些一般上下文:这是一个使用 MERN 堆栈的应用程序,但问题更具体到 AWS S3 数据。
我设置了一个 S3,并将我的应用程序中的图像和文件存储在那里。我通常使用服务器生成 signedURLs 并从浏览器直接上传。
在我的应用程序数据库中,我将 object URI 存储为一个字符串,然后存储一个图像,例如我可以使用 <img/>
标记渲染没问题。到目前为止一切顺利。
但是,当它们是 PDF 并且我想让用户下载我存储在 S3 中的 PDF 时,执行 <a href={s3Uri} download>
只会导致 pdf 在另一个 window/tab 中打开而不是提示用户下载。我相信这是由于下载属性依赖于 same-origin 并且您无法从外部资源下载文件(如果我错了请纠正我)
所以我的下一次尝试是直接使用 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())
})
所以通过这样做,我成功地读取了响应 headers(很有用,因为我可以以不同的方式处理 images/files)但是当我尝试读取返回的二进制数据时,我一直没有成功并解析它甚至确定它是如何编码的,它看起来像这样
%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,我将这些 PDF 作为 base64 字符串直接存储在我的数据库中。这些是我的应用程序生成的 PDF 并且相当小,所以我将它们直接存储在数据库中,而不是我存储在 AWS S3 中的 user-submitted 并且大小可能为几 MB(我的数据库中的是只有几 KB)
我用来处理我的 base64 pdf 并向用户提供可下载 link 的函数如下所示
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['Content-Type']};base64,${res.data}} />
我认为这是某种形式的 base64 的最大暗示是什么?
拜托!如果有人知道我如何在这里实现我的目标,我洗耳恭听!目标是能够提示用户下载我在 S3 URI 中拥有的资源。我可以 link 并且他们可以在浏览器中打开它,然后手动下载,但我想强制提示。
有人知道这里返回的是什么类型的数据吗?有什么方法可以将其解析为流?缓冲区?
我尝试用 JSON 将其字符串化或将其作为字符串记录到控制台,此时我愿意接受所有建议
您正在进行各种不必要的转换。当您执行 GET
请求时,您 已经 拥有所需格式的数据。
const response = await fetch(attachment.fileUrl,
headers: {Authorization: ''}}
});
const blob = await response.blob();
return URL.createObjectURL(res.data);
一些一般上下文:这是一个使用 MERN 堆栈的应用程序,但问题更具体到 AWS S3 数据。
我设置了一个 S3,并将我的应用程序中的图像和文件存储在那里。我通常使用服务器生成 signedURLs 并从浏览器直接上传。
在我的应用程序数据库中,我将 object URI 存储为一个字符串,然后存储一个图像,例如我可以使用 <img/>
标记渲染没问题。到目前为止一切顺利。
但是,当它们是 PDF 并且我想让用户下载我存储在 S3 中的 PDF 时,执行 <a href={s3Uri} download>
只会导致 pdf 在另一个 window/tab 中打开而不是提示用户下载。我相信这是由于下载属性依赖于 same-origin 并且您无法从外部资源下载文件(如果我错了请纠正我)
所以我的下一次尝试是直接使用 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())
})
所以通过这样做,我成功地读取了响应 headers(很有用,因为我可以以不同的方式处理 images/files)但是当我尝试读取返回的二进制数据时,我一直没有成功并解析它甚至确定它是如何编码的,它看起来像这样
%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,我将这些 PDF 作为 base64 字符串直接存储在我的数据库中。这些是我的应用程序生成的 PDF 并且相当小,所以我将它们直接存储在数据库中,而不是我存储在 AWS S3 中的 user-submitted 并且大小可能为几 MB(我的数据库中的是只有几 KB)
我用来处理我的 base64 pdf 并向用户提供可下载 link 的函数如下所示
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['Content-Type']};base64,${res.data}} />
我认为这是某种形式的 base64 的最大暗示是什么?
拜托!如果有人知道我如何在这里实现我的目标,我洗耳恭听!目标是能够提示用户下载我在 S3 URI 中拥有的资源。我可以 link 并且他们可以在浏览器中打开它,然后手动下载,但我想强制提示。
有人知道这里返回的是什么类型的数据吗?有什么方法可以将其解析为流?缓冲区?
我尝试用 JSON 将其字符串化或将其作为字符串记录到控制台,此时我愿意接受所有建议
您正在进行各种不必要的转换。当您执行 GET
请求时,您 已经 拥有所需格式的数据。
const response = await fetch(attachment.fileUrl,
headers: {Authorization: ''}}
});
const blob = await response.blob();
return URL.createObjectURL(res.data);