Flo*_*nig 0 amazon-s3 reactjs aws-sdk
我最近才接触AWS SDK,因此如果我的方法完全是胡说八道,请原谅。
我想将一个简单的媒体文件上传到我的 S3。我正在遵循本教程,到目前为止我可以毫无问题地上传文件。对于用户性来说,进度条将是一个很好的额外功能,因此我正在研究如何实现这一点。我很快发现当前的 AWS SDK v3不再支持httpUploadProgress,但我们应该使用@aws-sdk/lib-storage。使用这个库,我仍然可以将文件上传到 S3,但我无法让进度跟踪器工作!我认为这与我没有完全理解如何async在 React 组件中进行处理有关。
这是我的缩小组件示例(我在这里使用 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;
Run Code Online (Sandbox Code Playgroud)
所以基本上我看到事件被触发(开始文件上传)。然后需要一段时间,我才能Progress, 100在控制台中看到 Promise 结果和 。这对我来说意味着状态变量被更新(至少一次)但组件不会重新渲染?
我在这里做错了什么?任何帮助表示赞赏!
好吧,我已经找到解决方案了。状态变量上的回调工作正常并且执行其应该执行的操作。但对象的配置Upload已关闭。在深入研究源代码后,我发现只有当上传者上传了更多数据时才会触发事件侦听器。因为上传器会对上传进行分块,所以您有两个单独的配置参数,它们允许您将上传分成单独的块。所以
const upload = new Upload({
client: s3,
params: target,
queueSize: 4, // 4 is minimum
partSize: 5*1024*1024 // 5MB is minimum
});
Run Code Online (Sandbox Code Playgroud)
基本上当我们上传的文件大于 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
});
Run Code Online (Sandbox Code Playgroud)
显然,这可以做得更复杂,但我不想在这上面花太多时间,因为它不是原始问题的一部分。
如果您的文件足够大(> 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));
}
Run Code Online (Sandbox Code Playgroud)
也许这可以帮助有同样问题的人。
| 归档时间: |
|
| 查看次数: |
7182 次 |
| 最近记录: |