[英]How to download file from AWS S3 using getObject in Reactjs?
我正在尝试使用 React 直接从客户端将文件从 S3 存储桶下载到.csv 格式。 我已经能够毫无问题地上传文件,甚至可以列出存储桶中的所有文件,但是在使用 getObject 实际下载文件时遇到了麻烦。 我想要的文件保存在模板文件夹中,因此当从下拉列表中选择一个时,我的参数中的键会更改,并将获取该特定文件。
我曾尝试使用 Blob 获取通过在特定存储桶和文件本身上调用 getObject 接收到的 data.Body,但遇到一些文件无法下载或它在 Mac OS 上运行但在 Windows 上运行的问题,或者不适用于 Firefox 但适用于 Chrome,反之亦然。
我想知道是否有一种简单的方法可以仅使用 React 来做到这一点? 从文件中获取数据并将其转换为.csv?
这是我的 Downloads.js 文件,使用 React Bootstrap 作为下拉菜单能够 select 一个特定的文件名:
import React, { useState } from 'react';
import { ListGroup, Dropdown } from 'react-bootstrap';
import AWS from 'aws-sdk';
const InputDownload = () => {
const [template, setTemplate] = useState('Choose Template');
AWS.config.update({
accessKeyId: process.env.REACT_APP_ACCESS_ID,
secretAccessKey: process.env.REACT_APP_ACCESS_KEY,
});
const handleDownload = () => {
const s3 = new AWS.S3();
const params = {
Bucket: process.env.REACT_APP_INTERNAL_BUCKET_NAME,
Key: `templates/${template}`,
};
s3.getObject(params, (err, data) => {
if (err) {
console.log(err, err.stack);
} else {
console.log(data.Body.toString();
}
});
}
return (
<>
<form className='bg-white my-4'>
<Dropdown>
<Dropdown.Toggle variant='secondary' id='dropdown-basic'>
{template}
</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.Item onSelect={() => setTemplate('T1')}>
T1</Dropdown.Item>
<Dropdown.Item onSelect={() => setTemplate('IV1')}>
IV1
</Dropdown.Item>
<Dropdown.Item onSelect={() => setTemplate('IV2')}>
IV2
</Dropdown.Item>
<Dropdown.Item onSelect={() => setTemplate('DV1')}>
DV1
</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
<input
type='submit'
value='Download'
className='btn btn-primary btn-block mt-3'
onClick={handleDownload}
/>
</form>
</>
);
};
export default InputDownload;
任何帮助将不胜感激!
出于安全原因,我强烈建议在服务器端执行此操作。因为在节点环境中的 react 项目的构建过程将执行后,所有环境变量将直接设置为客户端上的字符串,每个人都可以访问它们( accessKeyId 和 secretAccessKey)。
客户端(浏览器或任何其他环境)无权访问您的服务器环境,这就是您在构建过程中传递这些变量的原因。
另一方面,服务器可以直接访问运行它的机器,这就是为什么在服务器端安全地使用环境变量的原因。
对于将来可能希望直接从客户端执行此操作的任何其他人,我能够通过使用 Blob 将数据转换为 Blob URL 然后在单击下载时运行 function 来实现此目的。
我上面的 InputDownload 文件现在看起来像这样:
import React, { useState } from 'react';
import { ListGroup, Dropdown } from 'react-bootstrap';
import AWS from 'aws-sdk';
const InputDownload = () => {
const [template, setTemplate] = useState('Choose Template');
AWS.config.update({
accessKeyId: process.env.REACT_APP_ACCESS_ID,
secretAccessKey: process.env.REACT_APP_ACCESS_KEY,
});
const handleClick = (e) => {
e.preventDefault();
};
const handleDownload = () => {
const s3 = new AWS.S3();
const params = {
Bucket: process.env.REACT_APP_INTERNAL_BUCKET_NAME,
Key: `templates/${template}`,
};
function downloadBlob(blob, name = `${template}.csv`) {
// Convert your blob into a Blob URL (a special url that points to an object in the browser's memory)
const blobUrl = URL.createObjectURL(blob);
// Create a link element
const link = document.createElement('a');
// Set link's href to point to the Blob URL
link.href = blobUrl;
link.download = name;
// Append link to the body
document.body.appendChild(link);
// Dispatch click event on the link
// This is necessary as link.click() does not work on the latest firefox
link.dispatchEvent(
new MouseEvent('click', {
bubbles: true,
cancelable: true,
view: window,
})
);
// Remove link from body
document.body.removeChild(link);
}
s3.getObject(params, (err, data) => {
if (err) {
console.log(err, err.stack);
} else {
let csvBlob = new Blob([data.Body.toString()], {
type: 'text/csv;charset=utf-8;',
});
downloadBlob(csvBlob, `${template}`);
}
});
}
return (
<>
<form className='bg-white my-4' onSubmit={handleClick}>
<Dropdown>
<Dropdown.Toggle variant='secondary' id='dropdown-basic'>
{template}
</Dropdown.Toggle>
<Dropdown.Menu>
<Dropdown.Item onSelect={() => setTemplate('T1')}>
T1</Dropdown.Item>
<Dropdown.Item onSelect={() => setTemplate('IV1')}>
IV1
</Dropdown.Item>
<Dropdown.Item onSelect={() => setTemplate('IV2')}>
IV2
</Dropdown.Item>
<Dropdown.Item onSelect={() => setTemplate('DV1')}>
DV1
</Dropdown.Item>
</Dropdown.Menu>
</Dropdown>
<input
type='submit'
value='Download'
className='btn btn-primary btn-block mt-3'
onClick={handleDownload}
/>
</form>
</>
);
};
export default InputDownload;
声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.