管理OSS目录

重要

本文中含有需要您注意的重要提示信息,忽略该信息可能对您的业务造成影响,请务必仔细阅读。

OSS中文件数量庞大时,所有文件平铺存储会导致查找困难、批量操作复杂。为了解决这些问题,OSS提供了目录功能,通过模拟文件夹的结构来组织和管理海量对象。

工作原理

OSS本质上是扁平存储,没有真正的文件夹。控制台所显示的“目录”,是OSS依据文件名中的/分隔符自动生成的。

当在控制台看到如下的层级结构时:

examplebucket
    └── log/
       ├── date1.txt
       ├── date2.txt  
       ├── date3.txt
    └── destfolder/
       └── 2021/
          ├── photo.jpg

实际上OSS只是存储了这些文件:

log/date1.txt
log/date2.txt
destfolder/2021/photo.jpg

创建目录

目录生成有两种方式:

  • 上传文件时自动生成:上传包含路径的文件时,相应的目录会自动出现。

  • 主动创建空目录:此操作的本质是创建一个以/结尾的0字节文件,以此作为空目录的占位符。

    控制台

    1. OSS管理控制台,进入目标Bucket文件管理 > 文件列表页面。

    2. 单击新建目录

    3. 输入目录名,然后单击确定

      目录命名规范如下:

      • 不允许使用表情符,请使用符合要求的UTF-8字符。
      • 正斜线/用于分割路径,可快速创建子目录,但不要以正斜线/或反斜线\开头,不要出现连续的正斜线/
      • 不允许出现名为..的子目录。
      • 总长度控制在1~254个字符。

    ossutil

    以下示例展示了如何在存储空间examplebucket中创建目录dir/

    ossutil mkdir oss://examplebucket/dir

    更多用法见mkdir(创建目录)

    SDK

    以下仅列举常见SDK创建目录的代码示例。关于其他SDK的创建目录的代码示例,请参见SDK简介

    import com.aliyun.oss.ClientException;
    import com.aliyun.oss.OSS;
    import com.aliyun.oss.common.auth.*;
    import com.aliyun.oss.OSSClientBuilder;
    import com.aliyun.oss.OSSException;
    import com.aliyun.oss.model.PutObjectRequest;
    import java.io.ByteArrayInputStream;
    
    public class Demo {
    
        public static void main(String[] args) throws Exception {
            // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
            String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
            // 强烈建议不要把访问凭证保存到工程代码里,否则可能导致访问凭证泄露,威胁您账号下所有资源的安全。本代码示例以从环境变量中获取访问凭证为例。运行本代码示例之前,请先配置环境变量。
            EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
            // 填写Bucket名称,例如examplebucket。
            String bucketName = "examplebucket";
            // 填写目录名称,目录需以正斜线结尾。
            String objectName = "exampledir/";
    
            // 创建OSSClient实例。
            OSS ossClient = new OSSClientBuilder().build(endpoint, credentialsProvider);
    
            try {            
                String content = "";
    
                // 创建PutObjectRequest对象。       
                PutObjectRequest putObjectRequest = new PutObjectRequest(bucketName, objectName, new ByteArrayInputStream(content.getBytes()));
                
                // 如果需要上传时设置存储类型和访问权限,请参考以下示例代码。
                // ObjectMetadata metadata = new ObjectMetadata();
                // metadata.setHeader(OSSHeaders.OSS_STORAGE_CLASS, StorageClass.Standard.toString());
                // metadata.setObjectAcl(CannedAccessControlList.Private);
                // putObjectRequest.setMetadata(metadata);
    
                // 上传字符串。
                ossClient.putObject(putObjectRequest);
            } 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\Credentials\EnvironmentVariableCredentialsProvider;
    use OSS\OssClient;
    use OSS\CoreOssException;
    // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_IDOSS_ACCESS_KEY_SECRET。
    $provider = new EnvironmentVariableCredentialsProvider();
    // yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
    $endpoint = "yourEndpoint";
    // 填写Bucket名称,例如examplebucket。
    $bucket= "examplebucket";
    // 填写目录名称,目录需以正斜线结尾。
    $object = "exampledir/";
    $content = "";
    try{
        $config = array(
            "provider" => $provider,
            "endpoint" => $endpoint,
        );
        $ossClient = new OssClient($config);
    
        $ossClient->putObject($bucket, $object, $content);
    } catch(OssException $e) {
        printf(__FUNCTION__ . ": FAILED\n");
        printf($e->getMessage() . "\n");
        return;
    }
    print(__FUNCTION__ . "OK" . "\n");
    
    // 上传时可以设置相关的headers,例如设置访问权限为private、自定义元数据等。
    $options = array(
        OssClient::OSS_HEADERS => array(
            'x-oss-object-acl' => 'private',
            'x-oss-meta-info' => 'your info'
        ),
    );
    try{
        $config = array(
            "provider" => $provider,
            "endpoint" => $endpoint,
        );
        $ossClient = new OssClient($config);
    
        $ossClient->putObject($bucket, $object, $content, $options);
    } 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',
      // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_IDOSS_ACCESS_KEY_SECRET。
      accessKeyId: process.env.OSS_ACCESS_KEY_ID,
      accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
      // 填写Bucket名称。
      bucket: 'examplebucket',
    });
    
    async function putBuffer () {
      try {
        // 填写目录名称,目录需以正斜线结尾。
        const result = await client.put('exampledir/', new Buffer(''));
        console.log(result);
      } catch (e) {
        console.log(e);
      }
    }
    
    putBuffer();
    # -*- coding: utf-8 -*-
    
    import oss2
    from oss2.credentials import EnvironmentVariableCredentialsProvider
    
    # 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_IDOSS_ACCESS_KEY_SECRET。
    auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider())
    # yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
    # 填写Bucket名称。
    bucket = oss2.Bucket(auth, 'https://oss-cn-hangzhou.aliyuncs.com', 'examplebucket')
    
    # 填写目录名称,目录需以正斜线结尾。
    bucket.put_object('exampledir/', '')    
    using System.Text;
    using Aliyun.OSS;
    
    // yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
    var endpoint = "yourEndpoint";
    // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_IDOSS_ACCESS_KEY_SECRET。
    var accessKeyId = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_ID");
    var accessKeySecret = Environment.GetEnvironmentVariable("OSS_ACCESS_KEY_SECRET");
    // 填写Bucket名称,例如examplebucket。
    var bucketName = "examplebucket";
    // 填写目录名称,目录需以正斜线结尾。
    var objectName = "exampledir/";
    var objectContent = "";
    
    // 创建OssClient实例。
    var client = new OssClient(endpoint, accessKeyId, accessKeySecret);
    try
    {
        byte[] binaryData = Encoding.ASCII.GetBytes(objectContent);
        MemoryStream requestContent = new MemoryStream(binaryData);
        // 创建目录。
        client.PutObject(bucketName, objectName, requestContent);
        Console.WriteLine("Put object succeeded");
    }
    catch (Exception ex)
    {
        Console.WriteLine("Put object failed, {0}", ex.Message);
    }
    #include "oss_api.h"
    #include "aos_http_io.h"
    /* yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。*/
    const char *endpoint = "yourEndpoint";
    
    /* 填写Bucket名称,例如examplebucket。*/
    const char *bucket_name = "examplebucket";
    /* 填写目录名称,目录需以正斜线结尾。*/
    const char *object_name = "exampledir/";
    const char *object_content = "";
    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);
        /* 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_IDOSS_ACCESS_KEY_SECRET。*/    
        aos_str_set(&options->config->access_key_id, getenv("OSS_ACCESS_KEY_ID"));
        aos_str_set(&options->config->access_key_secret, getenv("OSS_ACCESS_KEY_SECRET"));
        /* 是否使用了CNAME。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_list_t buffer;
        aos_buf_t *content = NULL;
        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_list_init(&buffer);
        content = aos_buf_pack(oss_client_options->pool, object_content, strlen(object_content));
        aos_list_add_tail(&content->node, &buffer);
        /* 上传文件。*/
        resp_status = oss_put_object_from_buffer(oss_client_options, &bucket, &object, &buffer, headers, &resp_headers);
        /* 判断上传是否成功。*/
        if (aos_status_is_ok(resp_status)) {
            printf("put object from buffer succeeded\n");
        } else {
            printf("put object from buffer failed\n");      
        }
        /* 释放内存池,相当于释放了请求过程中各资源分配的内存。*/
        aos_pool_destroy(pool);
        /* 释放之前分配的全局资源。*/
        aos_http_io_deinitialize();
        return 0;
    }

    ossbrowser

    1. 安装ossbrowser 2.0登录ossbrowser 2.0

    2. 进入目标Bucket,选择新建目录

    3. 输入目录名并确认保存

重命名目录

目录重命名并非单一的原子操作,无论使用何种工具,其底层原理都是一个复合工作流:

  1. 复制:将原目录下的所有文件递归地复制到一个新的目标目录下。

  2. 删除:确认复制成功后,将原目录及其下的所有文件彻底删除。

重要

由于重命名需要逐一复制和删除目录下的所有文件,该操作对大目录将非常耗时,并会产生大量的API调用和流量费用,请务必谨慎评估。

ossbrowser

ossbrowser将上述复杂的“复制-删除”工作流自动化了,用户只需在界面上进行一次操作即可。对于大多数场景,推荐优先使用此方式。

  1. 安装ossbrowser 2.0登录ossbrowser 2.0

  2. 选中目录,单击image,选择重命名

    image

  3. 设置新的目录名,然后单击确认修改

ossutil

使用ossutil时,需要手动执行复制删除两个核心步骤来完成重命名。

  1. 复制文件
    使用cp(拷贝文件)命令并附带--recursive (-r) 选项,将存储空间examplebucketold-dir/下的所有内容复制到new-dir/

    ossutil cp oss://examplebucket/old-dir/ oss://examplebucket/new-dir/ -r
  2. (可选)验证
    使用ls(列举账号级别下的资源)命令检查新目录,确保所有文件已成功复制。

    ossutil ls oss://examplebucket/new-dir/
  3. 删除原目录
    确认复制无误后,使用rm(删除)命令并附带--recursive (-r) 选项,删除原目录old-dir/

    警告

    此操作将永久删除old-dir/目录及其下的所有文件,删除后无法恢复,请务必谨慎操作。

    ossutil rm oss://examplebucket/old-dir/ -r

SDK

如上所述,通过SDK重命名目录需要组合多个API完成。具体实现可分别参考以下核心操作的SDK文档:

API

通过API重命名目录,需要组合以下API调用完成:

删除目录

警告

删除目录会同步删除目录下包含的子目录以及所有文件,请谨慎操作。

控制台

  1. 登录OSS管理控制台

  2. 进入目标Bucket文件管理 > 文件列表页面。

  3. 选择要删除的目录,单击操作列的彻底删除

  4. 在弹出的对话框中单击确定

    重要

    删除目录及文件期间,请勿刷新或关闭任务列表,否则会导致任务中断。

ossutil

以下示例展示了如何删除存储空间examplebucket下的目录test/

ossutil rm oss://examplebucket/test/ -r

更多用法见rm(删除)

SDK

您可以通过指定Prefix的方式删除目录及目录下的所有文件。例如,您希望删除存储空间examplebucket下目录log及该目录下的所有文件,请将示例代码中的Prefix参数指定为log/

import com.aliyun.oss.ClientException;
import com.aliyun.oss.OSS;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.OSSClientBuilder;
import com.aliyun.oss.OSSException;
import com.aliyun.oss.model.*;
import java.io.UnsupportedEncodingException;
import java.net.URLDecoder;
import java.util.ArrayList;
import java.util.List;

public class Demo {

    public static void main(String[] args) throws Exception {
        // yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
        String endPoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 强烈建议不要把访问凭证保存到工程代码里,否则可能导致访问凭证泄露,威胁您账号下所有资源的安全。本代码示例以从环境变量中获取访问凭证为例。运行本代码示例之前,请先配置环境变量。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "examplebucket";

        // 填写待删除目录的完整路径,完整路径中不包含Bucket名称。
        final String prefix = "log/";

        // 创建OSSClient实例。
        OSS ossClient = new OSSClientBuilder().build(endPoint, credentialsProvider);

        try {
            // 删除目录及目录下的所有文件。
            String nextMarker = null;
            ObjectListing objectListing = null;
            do {
                ListObjectsRequest listObjectsRequest = new ListObjectsRequest(bucketName)
                        .withPrefix(prefix)
                        .withMarker(nextMarker);

                objectListing = ossClient.listObjects(listObjectsRequest);
                if (objectListing.getObjectSummaries().size() > 0) {
                    List<String> keys = new ArrayList<String>();
                    for (OSSObjectSummary s : objectListing.getObjectSummaries()) {
                        System.out.println("key name: " + s.getKey());
                        keys.add(s.getKey());
                    }
                    DeleteObjectsRequest deleteObjectsRequest = new DeleteObjectsRequest(bucketName).withKeys(keys).withEncodingType("url");
                    DeleteObjectsResult deleteObjectsResult = ossClient.deleteObjects(deleteObjectsRequest);
                    List<String> deletedObjects = deleteObjectsResult.getDeletedObjects();
                    try {
                        for(String obj : deletedObjects) {
                            String deleteObj =  URLDecoder.decode(obj, "UTF-8");
                            System.out.println(deleteObj);
                        }
                    } catch (UnsupportedEncodingException e) {
                        e.printStackTrace();
                    }
                }

                nextMarker = objectListing.getNextMarker();
            } while (objectListing.isTruncated());
        } 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;
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
$accessKeyId = getenv("OSS_ACCESS_KEY_ID");
$accessKeySecret = getenv("OSS_ACCESS_KEY_SECRET");
// yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
$endpoint = "yourEndpoint";
// 填写Bucket名称。
$bucket = "examplebucket";

try {
   $ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint, false);
   $option = array(
      OssClient::OSS_MARKER => null,
      // 填写待删除目录的完整路径,完整路径中不包含Bucket名称。
      OssClient::OSS_PREFIX => "log/",
      OssClient::OSS_DELIMITER=>'',
   );
   $bool = true;
   while ($bool){
      $result = $ossClient->listObjects($bucket,$option);
      $objects = array();
      if(count($result->getObjectList()) > 0){
         foreach ($result->getObjectList() as $key => $info){
            printf("key name:".$info->getKey().PHP_EOL);
            $objects[] = $info->getKey();
         }
         // 删除目录及目录下的所有文件。
         $delObjects = $ossClient->deleteObjects($bucket, $objects);
         foreach ($delObjects as $info){
            $obj = strval($info);
            printf("Delete ".$obj." : Success" . PHP_EOL);
         }
      }

      if($result->getIsTruncated() === 'true'){
         $option[OssClient::OSS_MARKER] = $result->getNextMarker();
      }else{
         $bool = false;
      }
   }
   printf("Delete Objects : OK" . PHP_EOL);
} catch (OssException $e) {
   printf("Delete Objects : Failed" . PHP_EOL);
   printf($e->getMessage() . PHP_EOL);
   return;
}
const OSS = require('ali-oss');

const client = new OSS({
  // yourregion填写Bucket所在地域。以华东1(杭州)为例,Region填写为oss-cn-hangzhou。
  region: 'yourregion',
  // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
  accessKeyId: process.env.OSS_ACCESS_KEY_ID,
  accessKeySecret: process.env.OSS_ACCESS_KEY_SECRET,
  // 填写存储空间名称。
  bucket: 'yourbucketname'
});

// 处理请求失败的情况,防止promise.all中断,并返回失败原因和失败文件名。
async function handleDel(name, options) {
  try {
    await client.delete(name);
  } catch (error) {
    error.failObjectName = name;
    return error;
  }
}

// 删除多个文件。
async function deletePrefix(prefix) {
  const list = await client.list({
    prefix: prefix,
  });

  list.objects = list.objects || [];
  const result = await Promise.all(list.objects.map((v) => handleDel(v.name)));
  console.log(result);
}
// 删除目录及目录下的所有文件。
deletePrefix('log/')
# -*- coding: utf-8 -*-
import oss2
from oss2.credentials import EnvironmentVariableCredentialsProvider

# 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
auth = oss2.ProviderAuth(EnvironmentVariableCredentialsProvider())
# yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
# 填写Bucket名称。
bucket = oss2.Bucket(auth, 'https://oss-cn-hangzhou.aliyuncs.com', 'examplebucket')
prefix = "exampledir/"

# 删除目录及目录下的所有文件。
for obj in oss2.ObjectIterator(bucket, prefix=prefix):
    bucket.delete_object(obj.key)
package main

import (
    "fmt"
    "os"

    "github.com/aliyun/aliyun-oss-go-sdk/oss"
)

func main() {
    // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
    provider, err := oss.NewEnvironmentVariableCredentialsProvider()
    if err != nil {
        fmt.Println("Error:", err)
        os.Exit(-1)
    }

    // 创建OSSClient实例。
    // yourEndpoint填写Bucket对应的Endpoint,以华东1(杭州)为例,填写为https://oss-cn-hangzhou.aliyuncs.com。其它Region请按实际情况填写。
    client, err := oss.New("yourEndpoint", "", "", oss.SetCredentialsProvider(&provider))
    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)
    }
    
    marker := oss.Marker("")
    // 填写待删除目录的完整路径,完整路径中不包含Bucket名称。
    prefix := oss.Prefix("log/")
    count := 0
    for {
        lor, err := bucket.ListObjects(marker, prefix)
        if err != nil {
            fmt.Println("Error:", err)
            os.Exit(-1)
        }

        objects := []string{}
        for _, object := range lor.Objects {
            objects = append(objects, object.Key)
        }
        // 删除目录及目录下的所有文件。
        // 将oss.DeleteObjectsQuiet设置为true,表示不返回删除结果。
        delRes, err := bucket.DeleteObjects(objects, oss.DeleteObjectsQuiet(true))
        if err != nil {
            fmt.Println("Error:", err)
            os.Exit(-1)
        }

        if len(delRes.DeletedObjects) > 0 {
            fmt.Println("these objects deleted failure,", delRes.DeletedObjects)
            os.Exit(-1)
        }

        count += len(objects)

        prefix = oss.Prefix(lor.Prefix)
        marker = oss.Marker(lor.NextMarker)
        if !lor.IsTruncated {
            break
        }
    }
    fmt.Printf("success,total delete object count:%d\n", count)
}
#include <alibabacloud/oss/OssClient.h>
using namespace AlibabaCloud::OSS;

int main(void)
{
    /* 初始化OSS账号信息。*/
            
    /* yourEndpoint填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。*/
    std::string Endpoint = "yourEndpoint";
    /* 填写Bucket名称。*/
    std::string BucketName = "examplebucket";
    /* 填写待删除目录的完整路径,完整路径中不包含Bucket名称。*/
    std::string keyPrefix = "log/";

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

    ClientConfiguration conf;
    /* 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。*/
    auto credentialsProvider = std::make_shared<EnvironmentVariableCredentialsProvider>();
    OssClient client(Endpoint, credentialsProvider, conf);

    std::string nextMarker = "";
    bool isTruncated = false;
    do {            
            ListObjectsRequest request(BucketName);            
            request.setPrefix(keyPrefix);
            request.setMarker(nextMarker);
            auto outcome = client.ListObjects(request);

            if (!outcome.isSuccess()) {
                /* 异常处理。*/
                std::cout << "ListObjects fail" <<
                ",code:" << outcome.error().Code() <<
                ",message:" << outcome.error().Message() <<
                ",requestId:" << outcome.error().RequestId() << std::endl;
                break;
            }
            for (const auto& object : outcome.result().ObjectSummarys()) {
                DeleteObjectRequest request(BucketName, object.Key());
                /* 删除目录及目录下的所有文件。*/
                auto delResult = client.DeleteObject(request);
            }
            nextMarker = outcome.result().NextMarker();
            isTruncated = outcome.result().IsTruncated();
    } while (isTruncated);

    /* 释放网络等资源。*/
    ShutdownSdk();
    return 0;
}

ossbrowser

  1. 安装ossbrowser 2.0登录ossbrowser 2.0

  2. 选中目录,单击image图标。

  3. 选择删除,然后单击确认删除

API

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

查询目录的文件数量及大小

方式一:通过列举文件的方式临时查询

该方式适用于指定目录下文件数量较少(如一万以内),且以临时性查询为主的场景。

  1. 在目标Bucket的左侧导航栏, 选择文件管理 > 文件列表

  2. 单击目标目录右侧的统计

    filesize.jpg

方式二:通过存储空间清单的方式定期查询

该方式适用于指定目录的文件数量较大(百亿级)且需要定期查询的场景。

  1. 在目标Bucket的左侧导航栏, 选择数据管理 > Bucket 清单

  2. 单击创建清单,在设置清单报告规则面板,选择存储清单 Bucket、清单内容选择Object大小、按前缀匹配输入需要查询的目录名称(例如random_files/),其他参数保留默认配置。

    screenshot_2025-07-04_18-14-09

  3. 查看清单结果。

    1. 文件列表页面的/存储清单Bucket/清单id/data/路径下找到生成的清单结果文件。

      screenshot_2025-07-04_18-22-28

    2. 将清单结果文件下载到本地,查看该目录下的文件数量和大小。

      清单结果文件中A列数据代表Bucket名称,B列数据是该目录及目录下的所有文件列表,C列数据是目录和目录下的文件大小。

      screenshot_2025-07-04_18-28-44

更多存储空间清单信息,请参见存储空间清单

方式三:通过标量检索的方式结合多种条件查询

该方式适用于需要对指定目录下的文件数量和大小进行准实时统计,并且支持灵活条件筛选(如按前缀、时间、文件类型等)的场景。

  1. 在目标Bucket的左侧导航栏, 选择文件管理 > 数据索引

  2. 数据索引页面,单击立即开启,然后选择标量检索,单击确认开启

    说明

    开启标量检索需要等待一定的时间,具体等待时长取决于BucketObject的数量。

  3. 文件名设置为前缀匹配,并输入前缀匹配:random_files/,其他参数保留默认设置。

    image

  4. 设置输出方式

    • 对象排序方式选择按照默认排序排列。

    • 数据聚合选择按照文件大小求和输出。

      image

  5. 单击立即查询,可以看到最终统计到的random_files/目录下所有文件和总大小结果。

    image

更多标量检索信息,请参见标量检索

应用于生产

权限管理

OSS的权限管理基于文件前缀匹配,而不是目录文件本身。

例如,要授予用户只读访问 logs/ 目录下所有文件的权限。

  • 错误做法:尝试为 logs/ 这个0字节对象设置权限。

  • 正确做法:创建RAM策略,将Resource字段设置为 acs:oss:*:*:your-bucket-name/logs/*。该策略会匹配所有以 logs/ 为前缀的对象,无论 logs/ 目录的0字节占位符对象是否存在。

性能优化

  • 目录层级深度:避免过深的嵌套结构(如 a/b/c/d/.../file.log),因为列举操作的过滤逻辑会影响性能。

  • 大规模重命名:重命名包含大量文件的目录会产生大量API调用和流量费用,设计系统时应尽量避免。