使用Reaction将文件上载到AWS S3时使用进度处理程序 [英] Using progress handler when uploading files to AWS S3 with React

查看:32
本文介绍了使用Reaction将文件上载到AWS S3时使用进度处理程序的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我最近才接触AWS SDK,因此如果我的方法完全是胡说八道,请原谅。

我想将一个简单的媒体文件上传到我的S3。我一直在关注this tutorial,到目前为止,我可以毫无问题地上传文件。对于易用性而言,进度条将是一个不错的额外功能,因此我正在研究如何实现这一点。我很快发现current AWS SDK v3 does not support httpUploadProgress anymore,但我们应该使用@aws-sdk/lib-storage。使用此库,我仍然可以将文件上载到S3,但无法使进度跟踪器工作!我想这与我没有完全了解如何处理Reaction组件中的async有关。

这里是我的缩小组件示例(我在这里使用的是Chakra UI)

const TestAWS: React.FC = () => {
  const inputRef = useRef<HTMLInputElement | null>(null);
  const [progr, setProgr] = useState<number>();

  const region = "eu-west-1";
  const bucketname = "upload-test";

  const handleClick = async () => {
    inputRef.current?.click();
  };

  const handleChange = (e: any) => {

    console.log('Start file upload');

    const file = e.target.files[0];
    const target = {
      Bucket: bucketname,
      Key: `jobs/${file.name}`,
      Body: file,
    };

    const s3 = new S3Client({
      region: region,
      credentials: fromCognitoIdentityPool({
        client: new CognitoIdentityClient({ region: region }),
        identityPoolId: "---MY ID---",
      }),
    });

    const upload = new Upload({
      client: s3,
      params: target,
    });

    const t = upload.on("httpUploadProgress", progress => {
      console.log("Progress", progress);

      if (progress.loaded && progress.total) {
        console.log("loaded/total", progress.loaded, progress.total);
        setProgr(Math.round((progress.loaded / progress.total) * 100)); // I was expecting this line to be sufficient for updating my component
      }
    });
    await upload.done().then(r => console.log(r));
  };

console.log('Progress', progr);

return (
    <InputGroup onClick={handleClick}>
      <input ref={inputRef} type={"file"} multiple={false} hidden accept='video/*' onChange={e => handleChange(e)} />
      <Flex layerStyle='uploadField'>
        <Center w='100%'>
          <VStack>
            <PlusIcon />
            <Text>Choose Video File</Text>
          </VStack>
        </Center>
      </Flex>
      {progr && <Progress value={progr} />}
    </InputGroup>
  );
};

export default TestAWS;

所以基本上我看到事件被激发(开始文件上传)。然后需要一段时间,我在控制台中看到承诺结果和Progress, 100。对我来说,这意味着状态变量会更新(至少更新一次),但组件不会重新呈现?

我到底做错了什么?感谢任何帮助!

推荐答案

好的,我已经找到解决方案了。状态变量上的回调工作得很好,并且做了它应该做的事情。但Upload对象的配置已关闭。在深入研究源代码之后,我发现只有在上传器上传了更多数据时才会触发事件侦听器。因为Uploader将上传分块,所以您有两个单独的配置参数,这两个参数允许您将上传分成单独的块。因此

const upload = new Upload({
  client: s3,
  params: target,
  queueSize: 4,          // 4 is minimum
  partSize: 5*1024*1024  // 5MB is minimum
});

基本上在我们上载的文件大于5MB时执行作业!只有在那时事件才会再次触发并更新状态变量。

因为这个上传工具是用来处理大文件上传的,所以这是完全有意义的,我们只需要根据我们想要上传的文件来调整queueSizepartSize即可。类似于

let queueSize = 10;
const file = event.target.files[0];

let partSize = file.size / (10 * 1024 * 1024);    // 1/10th of the file size in MB

const upload = new Upload({
  client: s3,
  params: target,
  queueSize: partSize > 5 queueSize : undefined,
  partSize: partSize > 5 ? partsize : undefined
});

显然,这可以做得更复杂,但我不想在此花费太多时间,因为这不是原始问题的一部分。

结论

如果您的文件足够大(>;5MB),您将看到进度更新,具体取决于您选择拆分文件的区块数(5MB或更多)。

由于这只影响原始示例中的handleChange方法,为了完整起见,我将其发布

const handleChange = async ( event ) => {
  const file = event.target.files[0]

  const target = {
    Bucket: 'some-S3-bucket',
    Key: `jobs/${file.name}`,
    Body: file,
  };

  const s3 = new S3Client({
    region: 'your-region',
    credentials: fromCognitoIdentityPool({
      client: new CognitoIdentityClient({ region: 'your-region' }),
      identityPoolId: "your-id",
    }),
  });

  // this will default to queueSize=4 and partSize=5MB
  const upload = new Upload({
    client: s3,
    params: target
  });

  upload.on("httpUploadProgress", progress => {
    console.log('Current Progress', progress);
    setProgr(progress);
  });

  await upload.done().then(r => console.log(r));
} 

也许这对有相同问题的人有帮助。

这篇关于使用Reaction将文件上载到AWS S3时使用进度处理程序的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆