气势凌人的伤疤 · 数据库——游标-阿里云开发者社区· 3 周前 · |
腹黑的书包 · 山东省工业和信息化厅 市县动态 ...· 7 月前 · |
奋斗的竹笋 · 驼铃古道上的哈马丹 — 中华人民共和国外交部· 8 月前 · |
气势凌人的豆芽 · 测绘的行业标准规范和国家标准全部可下载_51 ...· 1 年前 · |
怕考试的日记本 · 校园全能高手漫画全文免费阅读_全能高手漫画全 ...· 1 年前 · |
爽快的跑步机 · 丰田公布豪华氢燃料电池概念车 剑指奔驰S级· 1 年前 · |
我可以在网上找到很多资源,介绍如何使用aws S3 V2跟踪上传到V2的进度,并收听以下事件:
.on('httpUploadProgress', event => {}
但是自从我将aws更新到V3之后,就没有侦听器了。我认为我现在必须使用中间件功能,但是我尝试了一些东西,但它没有成功。我还深入了 API参考文档 和 github储存库 ,但没有成功。
我目前的代码如下:
import { S3Client, PutObjectCommand } from '@aws-sdk/client-s3';
export const UploadToS3 = (credentials, fileData) => {
const s3 = new S3Client({
region: credentials.region,
credentials: {
accessKeyId: credentials.access_key,
secretAccessKey: credentials.secret_key,
sessionToken: credentials.session_token,
return new Promise((resolve) => {
s3.send(new PutObjectCommand({
Bucket: credentials.bucket,
Key: credentials.file,
Body: fileData,
};
如能提供任何帮助,将不胜感激。
发布于 2021-03-12 15:30:07
我遇到了完全相同的问题(从aws v2切换到v3),发现这是因为库对所有的
获取
请求和
Fetch
不支持跟踪上载进度
都使用了
获取
API。
为了解决这个问题,我用好的旧
requestHandler
交换了
Fetch
(至少用于
PUT
请求),这可以通过在初始化S3Client时提供一个自定义S3Client来实现。
import { S3Client } from '@aws-sdk/client-s3';
const myHttpHandler = new MyHttpHandler();
myHttpHandler.onProgress$.subscribe(progress => {
const percentComplete = progress.progressEvent.loaded / progress.progressEvent.total * 100;
console.log('upload progress', percentComplete);
const myClient = new S3Client({
endpoint: this.configService.s3Api,
region: 'eu',
credentials: { ... },
requestHandler: myHttpHandler
});
自定义请求处理程序只是从@aws/fetch-http-处理程序中扩展了
FetchHttpHandler
。如果方法是
PUT
,并且有一个主体(所以我们想上传一些东西),那么它使用一个自定义XHR处理程序-否则它只使用来自它的
super
类的
Fetch
处理程序。在XHR处理程序中,可以将某些东西绑定到XHR处理程序的
progress
事件--在我的示例中,我发出一个rxjs
Subject
,可以在自定义处理程序之外使用它。
import { FetchHttpHandler, FetchHttpHandlerOptions } from '@aws-sdk/fetch-http-handler';
import { HeaderBag, HttpHandlerOptions } from '@aws-sdk/types';
import { buildQueryString } from '@aws-sdk/querystring-builder';
import { HttpResponse, HttpRequest } from '@aws-sdk/protocol-http';
import { Subject } from 'rxjs';
class MyHttpHandler extends FetchHttpHandler {
private myRequestTimeout;
onProgress$: Subject<{ path: string, progressEvent: ProgressEvent }> = new Subject();
constructor({ requestTimeout }: FetchHttpHandlerOptions = {}) {
super({ requestTimeout });
this.myRequestTimeout = requestTimeout;
handle(request: HttpRequest, { abortSignal }: HttpHandlerOptions = {}): Promise<{ response: HttpResponse }> {
// we let XHR only handle PUT requests with body (as we want to have progress events here), the rest by fetch
if (request.method === 'PUT' && request.body) {
return this.handleByXhr(request, { abortSignal });
return super.handle(request, { abortSignal });
* handles a request by XHR instead of fetch
* this is a copy the `handle` method of the `FetchHttpHandler` class of @aws-sdk/fetch-http-handler
* replacing the `Fetch`part with XHR
private handleByXhr(request: HttpRequest, { abortSignal }: HttpHandlerOptions = {}): Promise<{ response: HttpResponse}> {
const requestTimeoutInMs = this.myRequestTimeout;
// if the request was already aborted, prevent doing extra work
if (abortSignal?.aborted) {
const abortError = new Error('Request aborted');
abortError.name = 'AbortError';
return Promise.reject(abortError);
let path = request.path;
if (request.query) {
const queryString = buildQueryString(request.query);
if (queryString) {
path += `?${queryString}`;
const { port, method } = request;
const url = `${request.protocol}//${request.hostname}${port ? `:${port}` : ''}${path}`;
// Request constructor doesn't allow GET/HEAD request with body
// ref: https://github.com/whatwg/fetch/issues/551
const body = method === 'GET' || method === 'HEAD' ? undefined : request.body;
const requestOptions: RequestInit = {
body,
headers: new Headers(request.headers),
method,
const myXHR = new XMLHttpRequest();
const xhrPromise = new Promise<{headers: string[], body: Blob, status: number}>((resolve, reject) => {
try {
myXHR.responseType = 'blob';
// bind the events
myXHR.onload = progressEvent => {
resolve({
body: myXHR.response,
headers: myXHR.getAllResponseHeaders().split('\n'),
status: myXHR.status
myXHR.onerror = progressEvent => reject(new Error(myXHR.responseText));
myXHR.onabort = progressEvent => {
const abortError = new Error('Request aborted');
abortError.name = 'AbortError';
reject(abortError);
// progress event musst be bound to the `upload` property
if (myXHR.upload) {
myXHR.upload.onprogress = progressEvent => this.onProgress$.next({ path, progressEvent });
myXHR.open(requestOptions.method, url);
// append headers
if (requestOptions.headers) {
(requestOptions.headers as Headers).forEach((headerVal, headerKey, headers) => {
if (['host', 'content-length'].indexOf(headerKey.toLowerCase()) >= 0) {
// avoid "refused to set unsafe header" error message
return;
myXHR.setRequestHeader(headerKey, headerVal);
myXHR.send(requestOptions.body);
} catch (e) {
console.error('S3 XHRHandler error', e);
reject(e);
const raceOfPromises = [
xhrPromise.then((response) => {
const fetchHeaders = response.headers;
const transformedHeaders: HeaderBag = {};
fetchHeaders.forEach(header => {
const name = header.substr(0, header.indexOf(':') + 1);
const val = header.substr(header.indexOf(':') + 1);
if (name && val) {
transformedHeaders[name] = val;
const hasReadableStream = response.body !== undefined;
// Return the response with buffered body
if (!hasReadableStream) {
return response.body.text().then(body => ({
response: new HttpResponse({
headers: transformedHeaders,
statusCode: response.status,
body,
// Return the response with streaming body
return {
response: new HttpResponse({
headers: transformedHeaders,
statusCode: response.status,
body: response.body,
this.requestTimeoutFn(requestTimeoutInMs),
if (abortSignal) {
raceOfPromises.push(
new Promise<never>((resolve, reject) => {
abortSignal.onabort = () => {
myXHR.abort();
return Promise.race(raceOfPromises);
private requestTimeoutFn(timeoutInMs = 0): Promise<never> {
return new Promise((resolve, reject) => {
if (timeoutInMs) {
setTimeout(() => {
const timeoutError = new Error(`Request did not complete within ${timeoutInMs} ms`);
timeoutError.name = 'TimeoutError';
reject(timeoutError);
}, timeoutInMs);
}
发布于 2021-01-15 14:31:25
纵观
github问题
,我刚刚发现
@aws-sdk/client-s3
不支持上传进度跟踪,因为它在封面下使用
fetchHttpHandler
。推荐的方法是使用
@aws-sdk/lib-storage
,我还没有尝试过,但看起来很有希望!
发布于 2022-09-02 13:44:57
我也面临着同样的问题,那就是我必须将aws从v2升级到v3,但是在v3中缺少了文件上传进度特性。原因是在JS中,v2 for S3文件上传时使用XHR进行浏览器网络请求,具有良好的进度跟踪接口。JS v3也使用了fetch,这提供了一些其他的优点,但缺点之一是它似乎还不支持上传进度,而且这个特性的进展非常缓慢。
但是现在JS v3有了一个名为@aws/xhr-http-处理程序的新包,它可以代替@aws/fetch处理程序来获得细粒度的文件上传进度,就像我们在v2中看到的那样。
您可以在链接 https://github.com/aws/aws-sdk-js-v3/tree/main/packages/xhr-http-handler 上找到相关代码。
import { S3Client } from '@aws-sdk/client-s3';
import { XhrHttpHandler } from '@aws-sdk/xhr-http-handler';
import { Upload } from '@aws-sdk/lib-storage';
const s3Client = new S3Client({
requestHandler: new XhrHttpHandler({}),
const upload = new Upload({
client:s3Client,
params: {
bucket,
upload.on("httpUploadProgress", (progress) => {
气势凌人的伤疤 · 数据库——游标-阿里云开发者社区 3 周前 |
奋斗的竹笋 · 驼铃古道上的哈马丹 — 中华人民共和国外交部 8 月前 |
爽快的跑步机 · 丰田公布豪华氢燃料电池概念车 剑指奔驰S级 1 年前 |