使用Reaction将文件上载到AWS S3时使用进度处理程序 [英] Using progress handler when uploading files to AWS S3 with React
问题描述
我最近才接触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时执行作业!只有在那时事件才会再次触发并更新状态变量。
因为这个上传工具是用来处理大文件上传的,所以这是完全有意义的,我们只需要根据我们想要上传的文件来调整queueSize
和partSize
即可。类似于
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屋!