进行分片上传时,文件(Object)会被切成若干个Part,这些Part被称为碎片。当您将这些Part上传到OSS服务端后,可以调用CompleteMultipartUpload将这些碎片(Part)组合成一个完整的Object。

背景信息

  • 使用支持断点续传的OSS管理工具传输文件时,也会产生Part。
  • Part在完成Object组合前,不能被读取。删除Bucket时,必须先删除Object和Part。
  • 除通过OSS控制台、SDK、ossutil命令行等工具手动删除Part以外,您还可以通过设置生命周期管理自动清理Bucket中长时间未执行CompleteMultipartUpload操作的Part,减少空间占用。具体操作请参见清理过期碎片

费用说明

对于分片上传过程中产生的Part,OSS会根据Part的存储类型、实际大小和时长收取存储费用。

Part的存储类型与Object的存储类型一致,但是Part无最小计量限制。即某个Part小于64 KB,仍然按照Part的实际大小计算。

关于Part存储费用的更多信息,请参见存储费用

重要 建议您及时完成分片上传或者取消分片上传,原因是已上传但未完成或未取消的分片会占用存储空间进而产生存储费用。

使用OSS控制台

  1. 登录OSS管理控制台
  2. 单击Bucket列表,然后单击目标Bucket名称。
  3. 在左侧导航栏,选择文件管理 > 文件列表
  4. 文件列表页面,单击碎片管理
  5. 碎片管理(Multipart)面板,删除碎片文件。
    • 如果要删除该存储空间所有的碎片文件,单击删除所有
    • 如果要删除部分碎片文件,请选中或搜索碎片文件,然后单击删除
  6. 在弹出的对话框中,单击确定

使用图形化管理工具ossbrowser

ossbrowser支持Object级别的操作与控制台支持的操作类似,请按照ossbrowser界面指引完成删除碎片的操作。关于如何使用ossbrowser,请参见快速使用ossbrowser

使用阿里云SDK

以下仅列举常见SDK的清理碎片代码示例。关于其他SDK的清理碎片代码示例,请参见SDK简介

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;

public class Demo {

    public static void main(String[] args) throws Exception {
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
        String accessKeyId = "yourAccessKeyId";
        String accessKeySecret = "yourAccessKeySecret";
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "examplebucket";
        // 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
        String objectName = "exampledir/exampleobject.txt";
        // 填写uploadId,例如0004B999EF518A1FE585B0C9360D****。uploadId来自于InitiateMultipartUpload返回的结果。
        String uploadId = "0004B999EF518A1FE585B0C9360D****";

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endpoint, accessKeyId, accessKeySecret);
        try {
            // 取消分片上传。
            AbortMultipartUploadRequest abortMultipartUploadRequest =
                    new AbortMultipartUploadRequest(bucketName, objectName, uploadId);
            ossClient.abortMultipartUpload(abortMultipartUploadRequest);
        } catch (OSSException oe) {
            System.out.println("Caught an OSSException, which means your request made it to OSS, "
                    + "but was rejected with an error response for some reason.");
            System.out.println("Error Message:" + oe.getErrorMessage());
            System.out.println("Error Code:" + oe.getErrorCode());
            System.out.println("Request ID:" + oe.getRequestId());
            System.out.println("Host ID:" + oe.getHostId());
        } catch (ClientException ce) {
            System.out.println("Caught an ClientException, which means the client encountered "
                    + "a serious internal problem while trying to communicate with OSS, "
                    + "such as not being able to access the network.");
            System.out.println("Error Message:" + ce.getMessage());
        } finally {
            if (ossClient != null) {
                ossClient.shutdown();
            }
        }
    }
}
<?php
if (is_file(__DIR__ . '/../autoload.php')) {
    require_once __DIR__ . '/../autoload.php';
}
if (is_file(__DIR__ . '/../vendor/autoload.php')) {
    require_once __DIR__ . '/../vendor/autoload.php';
}

use OSS\OssClient;
use OSS\Core\OssException;

// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
$accessKeyId = 'yourAccessKeyId';
$accessKeySecret = 'yourAccessKeySecret';
// Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
$endpoint = 'https://oss-cn-hangzhou.aliyuncs.com';
// 填写Bucket名称,例如examplebucket。
$bucket= 'examplebucket';
//填写不包含Bucket名称在内的Object完整路径,例如exampledir/exampleobject.txt。
$object = 'exampledir/exampleobject.txt';
// 填写uploadId,例如0004B999EF518A1FE585B0C9360D****。uploadId来自InitiateMultipartUpload返回的结果。
$upload_id = '0004B999EF518A1FE585B0C9360D****';

try{
    $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint);

    $ossClient->abortMultipartUpload($bucket, $object, $upload_id);
} catch(OssException $e) {
    printf(__FUNCTION__ . ": FAILED\n");
    printf($e->getMessage() . "\n");
    return;
}
print(__FUNCTION__ . ": OK" . "\n");            
const OSS = require('ali-oss');

const client = new OSS({
  // yourRegion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
  region: 'yourRegion',
  // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
  accessKeyId: 'yourAccessKeyId',
  accessKeySecret: 'yourAccessKeySecret',
  // 填写Bucket名称,例如examplebucket。
  bucket: 'examplebucket',
});

async function abortMultipartUpload() {
  // 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
  const name = 'exampledir/exampleobject.txt';
  // 填写uploadId。uploadId来自于multipartUpload返回的结果。
  const uploadId = '0004B999EF518A1FE585B0C9360D****'; 
  const result = await client.abortMultipartUpload(name, uploadId);
  console.log(result);
}

abortMultipartUpload();
# -*- coding: utf-8 -*-
import os
import oss2

# 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
auth = oss2.Auth('yourAccessKeyId', 'yourAccessKeySecret')
# Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
# 填写Bucket名称,例如examplebucket。
bucket = oss2.Bucket(auth, 'https://oss-cn-hangzhou.aliyuncs.com', 'examplebucket')
# 填写不能包含Bucket名称在内的Object完整路径,例如exampledir/exampleobject.txt。
key = 'exampledir/exampleobject.txt'
# 由init_multipart_upload接口返回的upload_id。
upload_id = 'yourUploadId'

# 取消指定upload_id的分片上传事件,已上传的分片会被删除。
bucket.abort_multipart_upload(key, upload_id)
using Aliyun.OSS;

// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
var endpoint = "yourEndpoint";
// 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
var accessKeyId = "yourAccessKeyId";
var accessKeySecret = "yourAccessKeySecret";
// 填写Bucket名称。
var bucketName = "examplebucket";
// 填写Object完整路径。Object完整路径中不能包含Bucket名称。
var objectName = "exampleobject.txt";
// 填写uploadId。
var uploadId = "yourUploadId";

// 创建OssClient实例。
var client = new OssClient(endpoint, accessKeyId, accessKeySecret);
// 初始化分片上传。
try
{
    var request = new InitiateMultipartUploadRequest(bucketName, objectName);
    var result = client.InitiateMultipartUpload(request);
    uploadId = result.UploadId;
    // 打印uploadId。
    Console.WriteLine("Init multi part upload succeeded");
    Console.WriteLine("Upload Id:{0}", result.UploadId);
}
catch (Exception ex)
{
    Console.WriteLine("Init multi part upload failed, {0}", ex.Message);
}
// 取消分片上传。
try
{
    var request = new AbortMultipartUploadRequest(bucketName, objectName, uploadId);
    client.AbortMultipartUpload(request);
    Console.WriteLine("Abort multi part succeeded, {0}", uploadId);
}
catch (Exception ex)
{
    Console.WriteLine("Abort multi part failed, {0}", ex.Message);
}
// 填写Bucket名称,例如examplebucket。
String bucketName = "examplebucket";
// 填写Object完整路径,例如exampledir/exampleobject.txt。Object完整路径中不能包含Bucket名称。
String objectName = "exampledir/exampleobject.txt";
// 填写uploadId。
String uploadId = "0004B999EF518A1FE585B0C9****";

// 取消分片上传。
AbortMultipartUploadRequest abort = new AbortMultipartUploadRequest(bucketName, objectName, uploadId);
AbortMultipartUploadResult abortResult = oss.abortMultipartUpload(abort);
package main
import (
    "fmt"
    "os"
    "github.com/aliyun/aliyun-oss-go-sdk/oss"
)
func main() {
    // 创建OSSClient实例。
    // yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
    // 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。
    client, err := oss.New("yourEndpoint", "yourAccessKeyId", "yourAccessKeySecret")
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }    
    // 填写Bucket名称。
    bucket, err := client.Bucket("examplebucket")
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    // 初始化一个分片上传事件。
    // 填写Object完整路径。Object完整路径中不能包含Bucket名称。
    imur, err := bucket.InitiateMultipartUpload("exampleobject.txt")
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
    // 取消分片上传。
    err = bucket.AbortMultipartUpload(imur)
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }
}
OSSAbortMultipartUploadRequest * abort = [OSSAbortMultipartUploadRequest new];
abort.bucketName = @"<bucketName>";
abort.objectKey = @"<objectKey>";
abort.uploadId = uploadId;

OSSTask * abortTask = [client abortMultipartUpload:abort];

[abortTask waitUntilFinished];

if (!abortTask.error) {
    OSSAbortMultipartUploadResult * result = abortTask.result;
    uploadId = result.uploadId;
} else {
    NSLog(@"multipart upload failed, error: %@", abortTask.error);
    return;
}           
#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;

int main(void)
{
    /* 初始化OSS账号信息 */
    std::string AccessKeyId = "yourAccessKeyId";
    std::string AccessKeySecret = "yourAccessKeySecret";
    std::string Endpoint = "yourEndpoint";
    /* 填写Bucket名称,例如examplebucket */
    std::string BucketName = "examplebucket";
    /* 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。 */
    std::string ObjectName = "exampledir/exampleobject.txt";

    /* 初始化网络等资源 */
    InitializeSdk();

    ClientConfiguration conf;
    OssClient client(Endpoint, AccessKeyId, AccessKeySecret, conf);
    InitiateMultipartUploadRequest initUploadRequest(BucketName, ObjectName);

    /* 初始化分片上传事件 */
    auto uploadIdResult = client.InitiateMultipartUpload(initUploadRequest);
    auto uploadId = uploadIdResult.result().UploadId();

    /* 取消分片上传 */
    AbortMultipartUploadRequest  abortUploadRequest(BucketName, ObjectName, uploadId);
    auto abortUploadIdResult = client.AbortMultipartUpload(abortUploadRequest);

    if (!abortUploadIdResult.isSuccess()) {
        /* 异常处理 */
        std::cout << "AbortMultipartUpload fail" <<
        ",code:" << outcome.error().Code() <<
        ",message:" << outcome.error().Message() <<
        ",requestId:" << outcome.error().RequestId() << std::endl;
        return -1;
    }

    /* 释放网络等资源 */
    ShutdownSdk();
    return 0;
}
#include "oss_api.h"
#include "aos_http_io.h"
/* yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。*/
const char *endpoint = "yourEndpoint";
/* 阿里云账号AccessKey拥有所有API的访问权限,风险很高。强烈建议您创建并使用RAM用户进行API访问或日常运维,请登录RAM控制台创建RAM用户。*/
const char *access_key_id = "yourAccessKeyId";
const char *access_key_secret = "yourAccessKeySecret";
/* 填写Bucket名称,例如examplebucket。*/
const char *bucket_name = "examplebucket";
/* 填写Object完整路径,完整路径中不能包含Bucket名称,例如exampledir/exampleobject.txt。*/
const char *object_name = "exampledir/exampleobject.txt";
void init_options(oss_request_options_t *options)
{
    options->config = oss_config_create(options->pool);
    /* 用char*类型的字符串初始化aos_string_t类型。*/
    aos_str_set(&options->config->endpoint, endpoint);
    aos_str_set(&options->config->access_key_id, access_key_id);
    aos_str_set(&options->config->access_key_secret, access_key_secret);
    /* 是否使用CNAME访问OSS服务。0表示不使用。*/
    options->config->is_cname = 0;
    /* 设置网络相关参数,比如超时时间等。*/
    options->ctl = aos_http_controller_create(options->pool, 0);
}
int main(int argc, char *argv[])
{
    /* 在程序入口调用aos_http_io_initialize方法来初始化网络、内存等全局资源。*/
    if (aos_http_io_initialize(NULL, 0) != AOSE_OK) {
        exit(1);
    }
    /* 用于内存管理的内存池(pool),等价于apr_pool_t。其实现代码在apr库中。*/
    aos_pool_t *pool;
    /* 重新创建一个内存池,第二个参数是NULL,表示没有继承其它内存池。*/
    aos_pool_create(&pool, NULL);
    /* 创建并初始化options,该参数包括endpoint、access_key_id、acces_key_secret、is_cname、curl等全局配置信息。*/
    oss_request_options_t *oss_client_options;
    /* 在内存池中分配内存给options。*/
    oss_client_options = oss_request_options_create(pool);
    /* 初始化Client的选项oss_client_options。*/
    init_options(oss_client_options);
    /* 初始化参数。*/
    aos_string_t bucket;
    aos_string_t object;
    aos_string_t upload_id;   
    aos_table_t *headers = NULL;
    aos_table_t *resp_headers = NULL;
    aos_status_t *resp_status = NULL; 
    aos_str_set(&bucket, bucket_name);
    aos_str_set(&object, object_name);
    aos_str_null(&upload_id);
    /* 初始化分片上传,获取一个上传ID(upload_id)。*/
    resp_status = oss_init_multipart_upload(oss_client_options, &bucket, &object, &upload_id, headers, &resp_headers);
    /* 判断是否初始化分片上传成功。 */
    if (aos_status_is_ok(resp_status)) {
        printf("Init multipart upload succeeded, upload_id:%.*s\n", 
               upload_id.len, upload_id.data);
    } else {
        printf("Init multipart upload failed, upload_id:%.*s\n", 
               upload_id.len, upload_id.data);
    }
    /* 取消这次分片上传。*/
    resp_status = oss_abort_multipart_upload(oss_client_options, &bucket, &object, &upload_id, &resp_headers);
    /* 判断取消分片上传是否成功。*/
    if (aos_status_is_ok(resp_status)) {
        printf("Abort multipart upload succeeded, upload_id::%.*s\n", 
               upload_id.len, upload_id.data);
    } else {
        printf("Abort multipart upload failed\n"); 
    }
    /* 释放内存池,相当于释放了请求过程中各资源分配的内存。*/
    aos_pool_destroy(pool);
    /* 释放之前分配的全局资源。*/
    aos_http_io_deinitialize();
    return 0;
}

使用命令行工具ossutil

关于使用ossutil删除Part的更多信息,请参见删除Part

使用REST API

如果您的程序自定义要求较高,您可以直接发起REST API请求。直接发起REST API请求需要手动编写代码计算签名。更多信息,请参见AbortMultipartUpload