标准接口

PutObject只能上传小于5GB的对象,如果需要上传超过5GB的对象,您必须使用分片上传模式。

初始化分片上传

使用createMultipartUpload接口创建分片上传任务,该接口会返回一个UploadId,客户端使用这个UploadId来上传分片。

startUpload: function () {
    console.log("upload")
    let key = "ExampleObject.txt"
    let localFile = "E:/movie/3.flv"
    let size = 0
    try {
        var stats = fs.statSync(localFile);
        if(stats.size <= this.partSize) {
            console.log('file size %d too small', stats.size)
            return
        }
        size = stats.size
        this.numPartsLeft = Math.ceil(size / this.partSize);
    } catch(err) {
        console.log('statSync err %s', err)
    }
    
    let createParams = {
        Bucket: this.bucket,
        Key: key,
    };
    this.s3Client.createMultipartUpload(createParams, (err, createRes) => {
        if (err) {
            console.log("createMultipartUpload error", err);
            return;
        } 

        console.log("createMultipartUpload success", createRes)
        this.createRes = createRes

        let partNum = 0
        let f = fs.createReadStream(localFile)
        f.on('readable', () => {
            while ((buf=f.read(this.partSize)) != null) {
                partNum++
                this.uploadPart(buf, partNum)
            }
        });
    });
},

上传分片

使用uploadPart接口可以进行分片上传

uploadPart: function(buf, partNum) {
    console.log('uploadPart #%d, length: %d', partNum, buf.length)
    let partParams = {
        Body: buf,
        PartNumber: String(partNum),
        Bucket: this.createRes.Bucket,
        Key: this.createRes.Key,
        UploadId: this.createRes.UploadId
    }
    this.s3Client.uploadPart(partParams, (err, data) => {
        if (err){
            console.log('uploadPart error:', err);
            this.abortMultipartUpload();
            return;
        }
        this.multipartMap.Parts[partParams.PartNumber - 1] = {
            ETag: data.ETag,
            PartNumber: Number(partParams.PartNumber)
        };
        console.log("uploadPart completed ", partParams.PartNumber);
        --this.numPartsLeft
        if (this.numPartsLeft > 0) 
            return;

        this.completeMultipartUpload();
    });
},

完成分片上传

使用completeMultipartUpload完成分片上传任务

completeMultipartUpload: function() {
    console.log("completeMultipartUpload");
    var params = {
        Bucket: this.createRes.Bucket,
        Key: this.createRes.Key,
        UploadId: this.createRes.UploadId,
        MultipartUpload: this.multipartMap,
    };
    this.s3Client.completeMultipartUpload(params, function(err, data) {
        if (err) {
            console.log('completeMultipartUpload err, ', err);
            this.abortMultipartUpload();
        } else {
            console.log('completeMultipartUpload success');
        }
    });
},

取消分片上传

使用abortMultipartUpload取消分片上传任务

abortMultipartUpload: function() {
    console.log("abortMultipartUpload");
    var params = {
        Bucket: this.createRes.Bucket,
        Key: this.createRes.Key,
        UploadId: this.createRes.UploadId
    };
    this.s3Client.abortMultipartUpload(params, function(err, data) {
        if (err) {
            console.log('abortMultipartUpload err, ', err);
        } else {
            console.log('abortMultipartUpload success');
        }
    });
},

列举分片

使用listParts可以根据UploadId列举已完成上传的分片。可以使用此接口实现断点续传,在客户端保存UploadId和对应的本地文件路径,重新上传的时候先通过listParts获取到已上传的分片,避免重复上传这些分片,从而实现断点续传

listParts: function(key, uploadId) {
    console.log("listParts");
    var params = {
        Bucket: this.bucket,
        Key: key,
        UploadId: uploadId
    };
    this.s3Client.listParts(params, function(err, data) {
        if (err) {
            console.log('listParts err, ', err);
        } else {
            console.log('listParts success, ', data);
        }
    });
},

列举未完成的分片上传任务

使用listMultipartUploads可以列举所有未完成上传的分片上传任务Id

listMultipartUploads: function() {
    console.log("listMultipartUploads");
    var params = {
        Bucket: this.bucket,
    };
    this.s3Client.listMultipartUploads(params, function(err, data) {
        if (err) {
            console.log('listMultipartUploads err, ', err);
        } else {
            console.log('listMultipartUploads success, ', data);
        }
    });
},