繁体   English   中英

如何使用 Reactjs 中的 getObject 从 AWS S3 下载文件?

[英]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.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM