列举文件

存储空间(Bucket)内的文件(Object)默认按照字母序排列。支持查看所有文件、按目录查看文件、或调整每页显示数量。

列举所有文件

最常用的操作,获取存储空间中的所有文件。

使用SDK

Java

更多用法请参见列举文件(Java SDK)

import com.aliyun.oss.*;
import com.aliyun.oss.common.auth.*;
import com.aliyun.oss.common.comm.SignVersion;
import com.aliyun.oss.model.*;
import java.util.List;

public class Demo {
    public static void main(String[] args) throws Exception {
        // Endpoint以华东1(杭州)为例,其它Region请按实际情况填写。
        String endpoint = "https://oss-cn-hangzhou.aliyuncs.com";
        // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
        EnvironmentVariableCredentialsProvider credentialsProvider = CredentialsProviderFactory.newEnvironmentVariableCredentialsProvider();
        // 填写Bucket名称,例如examplebucket。
        String bucketName = "examplebucket";
        // 设置最大个数。
        int maxKeys = 200;
        // 填写Bucket所在地域。以华东1(杭州)为例,Region填写为cn-hangzhou。
        String region = "cn-hangzhou";

        // 创建OSSClient实例。
        // 当OSSClient实例不再使用时,调用shutdown方法以释放资源。
        ClientBuilderConfiguration clientBuilderConfiguration = new ClientBuilderConfiguration();
        clientBuilderConfiguration.setSignatureVersion(SignVersion.V4);        
        OSS ossClient = OSSClientBuilder.create()
        .endpoint(endpoint)
        .credentialsProvider(credentialsProvider)
        .clientConfiguration(clientBuilderConfiguration)
        .region(region)               
        .build();

        try {
            String nextContinuationToken = null;
            ListObjectsV2Result result = null;

            // 分页列举,每次传入上次返回结果中的nextContinuationToken。
            do {
                ListObjectsV2Request listObjectsV2Request = new ListObjectsV2Request(bucketName).withMaxKeys(maxKeys);
                listObjectsV2Request.setContinuationToken(nextContinuationToken);
                result = ossClient.listObjectsV2(listObjectsV2Request);

                List<OSSObjectSummary> sums = result.getObjectSummaries();
                for (OSSObjectSummary s : sums) {
                    System.out.println("\t" + s.getKey());
                }

                nextContinuationToken = result.getNextContinuationToken();

            } while (result.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();
            }
        }
    }
}

Python

更多用法见列举文件(Python SDK V2)

import argparse
import alibabacloud_oss_v2 as oss

# 创建命令行参数解析器
parser = argparse.ArgumentParser(description="list objects v2 sample")
# 添加命令行参数 --region,表示存储空间所在的区域,必需参数
parser.add_argument('--region', help='The region in which the bucket is located.', required=True)
# 添加命令行参数 --bucket,表示存储空间的名称,必需参数
parser.add_argument('--bucket', help='The name of the bucket.', required=True)
# 添加命令行参数 --endpoint,表示其他服务可用来访问OSS的域名,非必需参数
parser.add_argument('--endpoint', help='The domain names that other services can use to access OSS')

def main():
    args = parser.parse_args()  # 解析命令行参数

    # 从环境变量中加载凭证信息,用于身份验证
    credentials_provider = oss.credentials.EnvironmentVariableCredentialsProvider()

    # 加载SDK的默认配置,并设置凭证提供者
    cfg = oss.config.load_default()
    cfg.credentials_provider = credentials_provider
    # 设置配置中的区域信息
    cfg.region = args.region
    # 如果提供了endpoint参数,则设置配置中的endpoint
    if args.endpoint is not None:
        cfg.endpoint = args.endpoint

    # 使用配置好的信息创建OSS客户端
    client = oss.Client(cfg)

    # 创建ListObjectsV2操作的分页器
    paginator = client.list_objects_v2_paginator()

    # 遍历对象列表的每一页
    for page in paginator.iter_page(oss.ListObjectsV2Request(
            bucket=args.bucket
        )
    ):
        # 遍历每一页中的对象
        for o in page.contents:
            # 打印对象的名称、大小和最后修改时间
            print(f'Object: {o.key}, {o.size}, {o.last_modified}')

if __name__ == "__main__":
    main()  # 脚本入口,当文件被直接运行时调用main函数

Go

更多用法见列举文件(Go SDK V2)

package main

import (
	"context"
	"flag"
	"log"

	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss"
	"github.com/aliyun/alibabacloud-oss-go-sdk-v2/oss/credentials"
)

// 定义全局变量
var (
	region     string // 存储区域
	bucketName string // 存储空间名称
)

// init函数用于初始化命令行参数
func init() {
	flag.StringVar(&region, "region", "", "The region in which the bucket is located.")
	flag.StringVar(&bucketName, "bucket", "", "The `name` of the bucket.")
}

func main() {
	// 解析命令行参数
	flag.Parse()

	// 检查bucket名称是否为空
	if len(bucketName) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, bucket name required")
	}

	// 检查region是否为空
	if len(region) == 0 {
		flag.PrintDefaults()
		log.Fatalf("invalid parameters, region required")
	}

	// 加载默认配置并设置凭证提供者和区域
	cfg := oss.LoadDefaultConfig().
		WithCredentialsProvider(credentials.NewEnvironmentVariableCredentialsProvider()).
		WithRegion(region)

	// 创建OSS客户端
	client := oss.NewClient(cfg)

	// 创建列出对象的请求
	request := &oss.ListObjectsV2Request{
		Bucket: oss.Ptr(bucketName),
	}

	// 创建分页器
	p := client.NewListObjectsV2Paginator(request)

	// 初始化页码计数器
	var i int
	log.Println("Objects:")

	// 遍历分页器中的每一页
	for p.HasNext() {
		i++

		// 获取下一页的数据
		page, err := p.NextPage(context.TODO())
		if err != nil {
			log.Fatalf("failed to get page %v, %v", i, err)
		}

		// 打印该页中的每个对象的信息
		for _, obj := range page.Contents {
			log.Printf("Object:%v, %v, %v\n", oss.ToString(obj.Key), obj.Size, oss.ToTime(obj.LastModified))
		}
	}
}

PHP

更多用法请参见列举文件(PHP SDK V2)

<?php

// 引入自动加载文件,确保依赖库能够正确加载
require_once __DIR__ . '/../vendor/autoload.php';

use AlibabaCloud\Oss\V2 as Oss;

// 定义命令行参数的描述信息
$optsdesc = [
    "region" => ['help' => 'The region in which the bucket is located.', 'required' => True], // Bucket所在的地域(必填)
    "endpoint" => ['help' => 'The domain names that other services can use to access OSS.', 'required' => False], // 访问域名(可选)
    "bucket" => ['help' => 'The name of the bucket', 'required' => True], // Bucket名称(必填)
];

// 将参数描述转换为getopt所需的长选项格式
// 每个参数后面加上":"表示该参数需要值
$longopts = \array_map(function ($key) {
    return "$key:";
}, array_keys($optsdesc));

// 解析命令行参数
$options = getopt("", $longopts);

// 验证必填参数是否存在
foreach ($optsdesc as $key => $value) {
    if ($value['required'] === True && empty($options[$key])) {
        $help = $value['help']; // 获取参数的帮助信息
        echo "Error: the following arguments are required: --$key, $help" . PHP_EOL;
        exit(1); // 如果必填参数缺失,则退出程序
    }
}

// 从解析的参数中提取值
$region = $options["region"]; // Bucket所在的地域
$bucket = $options["bucket"]; // Bucket名称

// 加载环境变量中的凭证信息
// 使用EnvironmentVariableCredentialsProvider从环境变量中读取Access Key ID和Access Key Secret
$credentialsProvider = new Oss\Credentials\EnvironmentVariableCredentialsProvider();

// 使用SDK的默认配置
$cfg = Oss\Config::loadDefault();
$cfg->setCredentialsProvider($credentialsProvider); // 设置凭证提供者
$cfg->setRegion($region); // 设置Bucket所在的地域
if (isset($options["endpoint"])) {
    $cfg->setEndpoint($options["endpoint"]); // 如果提供了访问域名,则设置endpoint
}

// 创建OSS客户端实例
$client = new Oss\Client($cfg);

// 创建Paginator对象,用于分页列出Bucket中的对象
// ListObjectsV2Paginator支持高效地分页遍历对象列表
$paginator = new Oss\Paginator\ListObjectsV2Paginator(client: $client);
$iter = $paginator->iterPage(new Oss\Models\ListObjectsV2Request(bucket: $bucket)); // 初始化分页迭代器

// 遍历对象分页结果
foreach ($iter as $page) {
    foreach ($page->contents ?? [] as $object) {
        // 打印每个对象的关键信息
        // 输出对象的Key、类型和大小
        print("Object: $object->key, $object->type, $object->size\n");
    }
}

C#

更多用法请参见列举文件(C# SDK V2)

using OSS = AlibabaCloud.OSS.V2;  // 为阿里云OSS SDK创建别名,简化后续使用

var region = "cn-hangzhou";  // 必须项,设置Bucket所在的区域(Region)。以华东1(杭州)为例,Region填写为cn-hangzhou
var endpoint = null as string;  // 可选项,指定访问OSS服务的域名。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com
var bucket = "your bucket name";  // 必须项,目标Bucket名称

// 加载OSS SDK的默认配置,此配置会自动从环境变量中读取凭证信息(如AccessKey)
var cfg = OSS.Configuration.LoadDefault();
// 显式设置使用环境变量获取凭证,用于身份验证(格式:OSS_ACCESS_KEY_ID、OSS_ACCESS_KEY_SECRET)
cfg.CredentialsProvider = new OSS.Credentials.EnvironmentVariableCredentialsProvider();
// 设置配置的Bucket区域
cfg.Region = region;   
// 若已指定了endpoint,则覆盖默认的endpoint 
if(endpoint != null) 
{
    cfg.Endpoint = endpoint;
} 

// 使用配置信息创建OSS客户端实例
using var client = new OSS.Client(cfg); 

// 调用ListObjectsV2Paginator方法,获取目标Bucket下所有对象。
var paginator = client.ListObjectsV2Paginator(new OSS.Models.ListObjectsV2Request()
{
    Bucket = bucket
});

//  输出存储空间内的所有对象信息
Console.WriteLine("Objects:");
await foreach (var page in paginator.IterPageAsync())  // 异步遍历每一页结果
{
    // 遍历当前页中的每个对象
    foreach (var content in page.Contents ?? [])
    {
        // 输出对象信息:、大小(字节)、最后修改时间
        Console.WriteLine($"Object:{content.Key}, {content.Size}, {content.LastModified}");
    }
}

Node.js

更多用法请参见列举文件(Node.js)

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,
  authorizationV4: true,
  // yourbucketname填写存储空间名称。
  bucket: 'yourbucketname'
});

async function list () {
  let continuationToken = null;
  // 每页列举20个文件。
  const maxKeys = 20;
  do {
    const result = await client.listV2({
      'continuation-token': continuationToken,
      'max-keys': maxKeys
      });
    continuationToken = result.nextContinuationToken;
        console.log(result);
  }while(continuationToken)
}

list();

Harmony

更多用法请参见列举文件

import Client, { RequestError } from '@aliyun/oss';

// 创建OSS客户端实例
const client = new Client({
  // 请替换为RAM用户的Access Key ID
  accessKeyId: 'yourAccessKeyId',
  // 请替换为RAM用户的Access Key Secret
  accessKeySecret: 'yourAccessKeySecret',
  // 填写Bucket所在的地域。例如,华东1(杭州)的Region为'oss-cn-hangzhou'
  region: 'oss-cn-hangzhou',
});


/**
 * 分页列出Bucket中的对象。
 * 使用listObjectsV2方法并结合continuationToken参数实现分页列出对象。
 */
const listObjectsV2WithContinuationToken = async () => {
  try {
    let continuationToken: string | undefined; // 分页标记,初始为空
    let isTruncated = true; // 是否还有更多对象需要列出

    // 循环列出对象,直到没有更多对象为止
    while (isTruncated) {
      const res = await client.listObjectsV2({
        bucket: 'yourBucketName', // Bucket名称,请替换为您实际使用的Bucket名称
        continuationToken, // 分页标记,用于获取下一页数据
      });

      // 打印当前页的对象及其元信息
      console.log(JSON.stringify(res));

      // 更新分页状态
      isTruncated = res.data.isTruncated; // 是否还有更多对象
      continuationToken = res.data.nextContinuationToken; // 下一页的分页标记
    }
  } catch (err) {
    // 捕获请求过程中的异常信息
    if (err instanceof RequestError) {
      console.log('code: ', err.code); // 错误代码
      console.log('message: ', err.message); // 错误消息
      console.log('requestId: ', err.requestId); // 请求ID
      console.log('status: ', err.status); // HTTP状态码
      console.log('ec: ', err.ec); // 错误码
    } else {
      console.log('unknown error: ', err);
    }
  }
};

// 调用listObjectsV2WithContinuationToken函数执行分页列出对象的操作
listObjectsV2WithContinuationToken();

Swift

更多用法请参见列举文件

import AlibabaCloudOSS
import Foundation
@main
struct Main {
    static func main() async {
        do {
            // 填写Bucket所在地域。以华东1(杭州)为例,Region填写为cn-hangzhou。
            let region = "cn-hangzhou"
            // 填写Bucket名称。
            let bucket = "yourBucketName"
            // 可选项,指定访问OSS服务的域名。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com
            let endpoint: String? = nil
            
            // 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
            let credentialsProvider = EnvironmentCredentialsProvider()
            // 配置OSS客户端参数
            let config = Configuration.default()
                .withRegion(region)        // 设置Bucket所在地域
                .withCredentialsProvider(credentialsProvider)  // 设置访问凭证
                
            // 设置Endpoint
            if let endpoint = endpoint {
                config.withEndpoint(endpoint)
            }
            
            // 创建OSS客户端实例
            let client = Client(config)
            // 创建分页请求对象,用于遍历存储桶中的所有对象(分页处理)
            let paginator = client.listObjectsV2Paginator(
                ListObjectsV2Request(
                    bucket: bucket // 指定要列出对象的Bucket名称
                )
            )
            // 遍历分页结果,逐页获取对象信息
            for try await page in paginator {
                // 遍历当前页中的对象列表
                for content in page.contents ?? [] {
                    // 输出对象元数据:对象名称、大小(字节)、最后修改时间
                    print("Object key:\(content.key ?? ""), size: \(String(describing: content.size)), last modified: \(String(describing: content.lastModified))")
                }
            }
        } catch {
            // 错误输出
            print("error:\(error)")
        }
    }
}

Ruby

更多用法请参见列举文件

require 'aliyun/oss'

client = Aliyun::OSS::Client.new(
  # 填写Bucket所在地域对应的Endpoint。以华东1(杭州)为例,Endpoint填写为https://oss-cn-hangzhou.aliyuncs.com。
  endpoint: 'https://oss-cn-hangzhou.aliyuncs.com',
  # 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
  access_key_id: ENV['OSS_ACCESS_KEY_ID'],
  access_key_secret: ENV['OSS_ACCESS_KEY_SECRET']
)

# 填写Bucket名称,例如examplebucket。
bucket = client.get_bucket('examplebucket')
# 列举所有文件。
objects = bucket.list_objects
objects.each { |o| puts o.key }     

Browser.js

更多用法请参见列举文件

<!DOCTYPE html>
<html lang="en">
  <head>
    <meta charset="UTF-8" />
    <meta name="viewport" content="width=device-width, initial-scale=1.0" />
    <title>Document</title>
    <script src="https://gosspublic.alicdn.com/aliyun-oss-sdk-6.18.0.min.js"></script>
  </head>
  <body>
    <script>      
      const client = new OSS({
        // yourRegion填写Bucket所在地域。以华东1(杭州)为例,yourRegion填写为oss-cn-hangzhou。
        region: "yourRegion",
        authorizationV4: true,
        // 从STS服务获取的临时访问密钥(AccessKey ID和AccessKey Secret)。
        accessKeyId: 'yourAccessKeyId',
        accessKeySecret: 'yourAccessKeySecret',
        // 从STS服务获取的安全令牌(SecurityToken)。
        stsToken: 'yourSecurityToken',
        // 填写Bucket名称,例如examplebucket。
        bucket: "examplebucket",
      });

      async function list(dir) {
        try {
          // 默认最多返回1000个文件。
          let result = await client.list();
          console.log(result);

          // 从上一次list操作读取的最后一个文件的下一个文件开始继续获取文件列表。
          if (result.isTruncated) {
            result = await client.list({ marker: result.nextMarker });
          }

          // 列出前缀为'ex'的文件。
          result = await client.list({
            prefix: "ex",
          });
          console.log(result);

          // 列出前缀为'ex'且文件名称字母序'example'之后的文件。
          result = await client.list({
            prefix: "ex",
            marker: "example",
          });
          console.log(result);
        } catch (e) {
          console.log(e);
        }
      }

      list();
    </script>
  </body>
</html>
          

Android

更多用法请参见列举文件

private String marker = null;
private boolean isCompleted = false;

// 分页列举所有object。
public void getAllObject() {
    do {
        OSSAsyncTask task = getObjectList();
        // 阻塞等待请求完成获取NextMarker,请求下一页时需要将请求的marker设置为上一页请求返回的NextMarker。第一页无需设置。
        // 示例中通过循环分页列举数据,因此需要阻塞等待请求完成获取NextMarker才能请求下一页数据,实际使用时可根据实际场景判断是否需要阻塞。
        task.waitUntilFinished();
    } while (!isCompleted);
}

// 列举一页文件。
public OSSAsyncTask getObjectList() {
    // 填写Bucket名称。
    ListObjectsRequest request = new ListObjectsRequest("examplebucket");
    // 填写每页返回文件的最大个数。如果不设置此参数,则默认值为100,maxkeys的取值不能大于1000。
    request.setMaxKeys(20);
    request.setMarker(marker);

    OSSAsyncTask task = oss.asyncListObjects(request, new OSSCompletedCallback<ListObjectsRequest, ListObjectsResult>() {
        @Override
        public void onSuccess(ListObjectsRequest request, ListObjectsResult result) {
            for (OSSObjectSummary objectSummary : result.getObjectSummaries()) {
                Log.i("ListObjects", objectSummary.getKey());
            }
            // 最后一页。
            if (!result.isTruncated()) {
                isCompleted = true;
                return;
            }
            // 下一次列举文件的marker。
            marker = result.getNextMarker();
        }

        @Override
        public void onFailure(ListObjectsRequest request, ClientException clientException, ServiceException serviceException) {
            isCompleted = true;
            // 请求异常。
            if (clientException != null) {
                // 客户端异常,例如网络异常等。
                clientException.printStackTrace();
            }
            if (serviceException != null) {
                // 服务端异常。
                Log.e("ErrorCode", serviceException.getErrorCode());
                Log.e("RequestId", serviceException.getRequestId());
                Log.e("HostId", serviceException.getHostId());
                Log.e("RawMessage", serviceException.getRawMessage());
            }
        }
    });
    return task;
}

C++

更多用法请参见列举文件

#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";
    /* yourRegion填写Bucket所在地域对应的Region。以华东1(杭州)为例,Region填写为cn-hangzhou。*/
    std::string Region = "yourRegion";
    /* 填写Bucket名称,例如examplebucket。*/
    std::string BucketName = "examplebucket";

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

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

    std::string nextMarker = "";
    bool isTruncated = false; 
    do {
        /* 列举文件。*/
        ListObjectsRequest request(BucketName);
        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;
            ShutdownSdk();
            return -1;  
        }
        else {
            for (const auto& object : outcome.result().ObjectSummarys()) {
                std::cout << "object"<<
                ",name:" << object.Key() <<
                ",size:" << object.Size() <<
                ",lastmodify time:" << object.LastModified() << std::endl;
            }      
        }
        nextMarker = outcome.result().NextMarker();
        isTruncated = outcome.result().IsTruncated();
    } while (isTruncated);

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

iOS

更多用法请参见列举文件

 do {
    OSSGetBucketRequest *getBucket = [OSSGetBucketRequest new];
    getBucket.bucketName = @"examplebucket";
    getBucket.marker = _marker;  // Accessing the _marker instance variable
    getBucket.maxKeys = 20;

    OSSTask *getBucketTask = [client getBucket:getBucket];
    [getBucketTask continueWithBlock:^id(OSSTask *task) {
        if (!task.error) {
            OSSGetBucketResult *result = task.result;
            NSLog(@"Get bucket success!");
            NSLog(@"objects: %@", result.contents);
            if (result.isTruncated) {
                _marker = result.nextMarker;  // Update the _marker instance variable
                _isCompleted = NO;
            } else {
                _isCompleted = YES;
            }
        } else {
            _isCompleted = YES;
            NSLog(@"Get bucket failed, error: %@", task.error);
        }
        return nil;
    }];
    // 实现同步阻塞等待任务完成。
    [getBucketTask waitUntilFinished];
} while (!_isCompleted);

C

更多用法请参见列举文件

#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";
/* yourRegion填写Bucket所在地域对应的Region。以华东1(杭州)为例,Region填写为cn-hangzhou。*/
const char *region = "yourRegion";
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_ID和OSS_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"));
    //需要额外配置以下两个参数
    aos_str_set(&options->config->region, region);
    options->config->signature_version = 4;
    /* 是否设置了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、access_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_status_t *resp_status = NULL; 
    oss_list_object_params_t *params = NULL;
    oss_list_object_content_t *content = NULL;
    int size = 0;
    char *line = NULL;
    char *prefix = "";
    char *nextMarker = "";
    aos_str_set(&bucket, bucket_name);
    params = oss_create_list_object_params(pool);
    /* 通过max_ret参数设置需要返回的文件数量。*/
    /* 默认列举文件数量最多为1000个。如果列举的文件数量超出1000,则只返回按字母排序的前1000个文件,且返回结果中的truncated为true,并返回next_marker作为下次读取的起点。*/
    params->max_ret = 100;
    aos_str_set(&params->prefix, prefix);
    aos_str_set(&params->marker, nextMarker);
    printf("Object\tSize\tLastModified\n");
    /* 列举所有文件。*/
    do {
        resp_status = oss_list_object(oss_client_options, &bucket, params, NULL);
        if (!aos_status_is_ok(resp_status))
        {
            printf("list object failed\n");
            break;
        }
        aos_list_for_each_entry(oss_list_object_content_t, content, &params->object_list, node) {
            ++size;
            line = apr_psprintf(pool, "%.*s\t%.*s\t%.*s\n", content->key.len, content->key.data, 
                content->size.len, content->size.data, 
                content->last_modified.len, content->last_modified.data);
            printf("%s", line);
        }
        nextMarker = apr_psprintf(pool, "%.*s", params->next_marker.len, params->next_marker.data);
        aos_str_set(&params->marker, nextMarker);
        aos_list_init(&params->object_list);
        aos_list_init(&params->common_prefix_list);
    } while (params->truncated == AOS_TRUE);
    printf("Total %d\n", size);
    /* 释放内存池,相当于释放了请求过程中各资源分配的内存。*/
    aos_pool_destroy(pool);
    /* 释放之前分配的全局资源。*/
    aos_http_io_deinitialize();
    return 0;
}

使用ossutil

以下示例展示了如何列举存储空间examplebucket中所有Object的信息。

ossutil api list-objects-v2 --bucket examplebucket

更多用法见list-objects-v2(get-bucket-v2)

使用OSS控制台

  1. 登录OSS管理控制台

  2. 在左侧导航栏,单击Bucket 列表

  3. 进入目标Bucket,单击文件管理 > 文件列表

    当前页面将分页显示Bucket内的所有Object,默认每页显示50Object,最多可显示500个。

列举指定目录下所有文件

如果需要获取一个目录下(包含其所有子目录)的全部文件,形成一个扁平化的完整列表,只需设置 prefix参数即可。

prefix的作用是按前缀筛选,它会返回所有文件名(Key)以此字符串开头的对象。由于OSS采用的是扁平存储结构(没有物理文件夹),这个简单的筛选就能有效地获取逻辑目录下的所有内容。

使用SDK

Java

完整代码示例请参见列举文件(Java SDK)

// ...

// 关键代码:设置前缀
ListObjectsV2Request listObjectsV2Request = new ListObjectsV2Request(bucketName);
listObjectsV2Request.setPrefix("images/");  // 指定前缀
ListObjectsV2Result result = ossClient.listObjectsV2(listObjectsV2Request);

// ...

Python

完整代码示例请参见列举文件(Python SDK V2)

# ...

# 关键代码:添加prefix参数
for page in paginator.iter_page(oss.ListObjectsV2Request(
    bucket='your-bucket',
    prefix='images/'  # 指定前缀
)):
# ...

Go

完整代码示例请参见列举文件(Go SDK V2)

// ...
// 关键代码:设置前缀
request := &oss.ListObjectsV2Request{
Bucket: oss.Ptr(bucketName),
Prefix: oss.Ptr("images/"), // 列举指定前缀的所有对象
}
// ...

Node.js

完整代码示例请参见列举文件(Node.js)

// ...

// 关键代码:设置前缀
const result = await client.listV2({
    prefix: 'images/'  // 指定前缀
});

// ...

Harmony

完整代码示例请参见列举文件

// ...

// 关键代码:设置前缀
const res = await client.listObjectsV2({
    bucket: 'yourBucketName',
    prefix: 'images/',  // 指定前缀
});

// ...

Ruby

完整代码示例请参见列举文件

# ...

# 关键代码:设置前缀
objects = bucket.list_objects(:prefix => 'images/')  # 指定前缀

# ...

Android

完整代码示例请参见列举文件

// ...

// 关键代码:设置前缀
ListObjectsRequest request = new ListObjectsRequest("examplebucket");
request.setPrefix("images/");  // 指定前缀

// ...

C++

完整代码示例请参见列举文件

// ...

// 关键代码:设置前缀
ListObjectsRequest request(BucketName);
request.setPrefix("images/");  // 指定前缀

// ...

iOS

完整代码示例请参见列举文件

// ...

// 关键代码:设置前缀
getBucket.prefix = @"images/";  // 指定前缀

// ...

C

完整代码示例请参见列举文件

// ...

// 关键代码:设置前缀
char *prefix = "images/";  // 指定前缀
aos_str_set(&params->prefix, prefix);

// ...

使用ossutil

以下示例展示了如何列举存储空间examplebucket中指定前缀dir下的所有Object的信息。

ossutil api list-objects-v2 --bucket examplebucket --prefix dir/

更多用法见list-objects-v2(get-bucket-v2)

输出结果示例

假设Bucket中有以下文件:

images/cat.jpg
images/dog.png
images/archive/old.zip
readme.txt

当请求设置为 prefix="images/" 时,会返回:

images/
images/archive/
images/archive/old.zip
images/cat.jpg
images/dog.png

列举指定目录下的直属文件和子目录

在 prefix 的基础上,增加 delimiter 参数(通常设为 /)。这会将返回结果分为 文件(objects) 和 子目录(commonPrefixes) 两部分。

delimiter的作用是按层级分组。当它存在时,OSS会对prefix筛选后的结果进行二次处理:

  • 如果文件名在prefix之后不再包含/,则被视为文件

  • 如果文件名在prefix之后还包含/,则从开头到第一个/的部分会被视为一个子目录

使用SDK

Java

完整代码示例请参见列举文件(Java SDK)

// ...

// 关键代码:设置分隔符
ListObjectsV2Request listObjectsV2Request = new ListObjectsV2Request(bucketName);
listObjectsV2Request.setPrefix("images/");  // 指定目录
listObjectsV2Request.setDelimiter("/");     // 设置分隔符
ListObjectsV2Result result = ossClient.listObjectsV2(listObjectsV2Request);

// 遍历当前目录下的文件
for (OSSObjectSummary objectSummary : result.getObjectSummaries()) {
    System.out.println("文件: " + objectSummary.getKey());
}

// 遍历子目录
for (String commonPrefix : result.getCommonPrefixes()) {
    System.out.println("子目录: " + commonPrefix);
}

// ...

Python

完整代码示例请参见列举文件(Python SDK V2)

# ...

# 关键代码:添加delimiter参数
for page in paginator.iter_page(oss.ListObjectsV2Request(
    bucket=args.bucket,
    prefix="images/",  # 指定目录
    delimiter="/",     # 设置分隔符
)):
    # 遍历当前目录下的文件
    for file in page.contents:
        print(f'文件: {file.key}')
    
    # 遍历子目录
    for prefix in page.common_prefixes:
        print(f'子目录: {prefix.prefix}')

# ...

Go

// ...

// 关键代码:设置分隔符
request := &oss.ListObjectsV2Request{
    Bucket:    oss.Ptr(bucketName),
    Prefix:    oss.Ptr("images/"),  // 指定目录
    Delimiter: oss.Ptr("/"),        // 设置分隔符
}

// 遍历当前目录下的文件
for _, obj := range lsRes.Contents {
    log.Printf("文件: %v\n", oss.ToString(obj.Key))
}

// 遍历子目录
for _, prefix := range lsRes.CommonPrefixes {
    log.Printf("子目录: %v\n", *prefix.Prefix)
}

// ...

PHP

完整代码示例请参见列举文件(PHP SDK V2)

// ...

// 关键代码:创建分页器,并设置 delimiter 以区分文件和子目录
$paginator = new Oss\Paginator\ListObjectsV2Paginator(client: $client);
$iter = $paginator->iterPage(new Oss\Models\ListObjectsV2Request(
    bucket: $bucket,
    prefix: "",
    delimiter: "/"
));

// 遍历分页结果
foreach ($iter as $page) {
    // 遍历 contents 获取当前目录下的文件
    foreach ($page->contents ?? [] as $object) {
        echo "文件: " . $object->key . PHP_EOL;
    }

    // 遍历 commonPrefixes 获取子目录
    foreach ($page->commonPrefixes ?? [] as $prefixObject) {
        echo "子目录: " . $prefixObject->prefix . PHP_EOL;
    }
}

// ...

Node.js

完整代码示例请参见列举文件(Node.js)

// ...
// 关键代码:设置分隔符
const result = await client.listV2({
prefix: dir, // 指定目录
delimiter: '/' // 设置分隔符
});
// 遍历当前目录下的文件
if (result && result.objects) {
result.objects.forEach(obj => {
console.log('文件: %s', obj.name);
});
}
// 遍历子目录
if (result && result.prefixes) {
result.prefixes.forEach(subDir => {
console.log('子目录: %s', subDir);
});
}
// ...

Harmony

完整代码示例请参见列举文件

// ...
// 关键代码:设置分隔符
const res = await client.listObjectsV2({
bucket: 'yourBucketName', // Bucket名称
prefix: 'images/', // 指定目录
delimiter: '/', // 设置分隔符
});
// 遍历当前目录下的文件
if (res && res.objects) {
res.objects.forEach(obj => {
console.log('文件:', obj.name);
});
}
// 遍历子目录
if (res && res.prefixes) {
res.prefixes.forEach(subDir => {
console.log('子目录:', subDir);
});
}
// ...

Browser.js

完整代码示例请参见列举文件

// ...
// 关键代码:设置分隔符
let result = await client.list({
prefix: 'images/', // 指定目录
delimiter: "/", // 设置分隔符
});
// 遍历当前目录下的文件
result.objects.forEach(function (obj) {
console.log("文件: %s", obj.name);
});
// 遍历子目录
result.prefixes.forEach(function (subDir) {
console.log("子目录: %s", subDir);
});
// ...

Ruby

完整代码示例请参见列举文件

// ...
// 关键代码:设置分隔符
objects = bucket.list_objects(prefix: 'images/', delimiter: '/')
// 遍历当前目录下的文件
if obj.is_a?(Aliyun::OSS::Object)
puts "文件: #{obj.key}"
end
// 遍历子目录
if obj.is_a?(String) # Common Prefix
puts "子目录: #{obj}"
end
// ...

C++

完整代码示例请参见列举文件

// ...
// 关键代码:设置分隔符
ListObjectsRequest request(BucketName);
request.setPrefix("images/"); // 指定目录
request.setDelimiter("/"); // 设置分隔符
// 遍历当前目录下的文件
for (const auto& object : outcome.result().ObjectSummarys()) {
std::cout << "文件:" << object.Key() << std::endl;
}
// 遍历子目录
for (const auto& commonPrefix : outcome.result().CommonPrefixes()) {
std::cout << "子目录:" << commonPrefix << std::endl;
}
// ...

C

完整代码示例请参见列举文件

// ...
// 关键代码:设置分隔符
params = oss_create_list_object_params(pool);
aos_str_set(&params->prefix, "images/"); // 指定目录
aos_str_set(&params->delimiter, "/"); // 设置分隔符
// 遍历当前目录下的文件
aos_list_for_each_entry(oss_list_object_content_t, content, &params->object_list, node) {
printf("文件: %.*s\n", content->key.len, content->key.data);
}
// 遍历子目录
aos_list_for_each_entry(oss_list_object_common_prefix_t, commonPrefix, &params->common_prefix_list, node) {
printf("子目录: %.*s\n", commonPrefix->prefix.len, commonPrefix->prefix.data);
}
// ...

使用ossutil

以下示例展示了如何列举存储空间examplebucket中当前目录下的Object的信息。

ossutil api list-objects-v2 --bucket examplebucket --prefix images/ --delimiter /

更多用法见list-objects-v2(get-bucket-v2)

输出结果示例

当请求同时设置为prefix="images/"和 delimiter="/" 时,结果会被分组:

文件:
images/
images/cat.jpg
images/dog.png
目录:
images/archive/

列举指定位置后的文件

使用 startAfter 参数(部分旧版SDK使用 marker),可以跳过所有按字母序排在该文件名之前的文件。

使用SDK

Java

完整代码示例请参见列举文件(Java SDK)

// ...

// 关键代码:设置起始位置
ListObjectsV2Request listObjectsV2Request = new ListObjectsV2Request(bucketName);
listObjectsV2Request.setStartAfter("images/cat.jpg");  // 从指定文件后开始
ListObjectsV2Result result = ossClient.listObjectsV2(listObjectsV2Request);

// ...

Python

完整代码示例请参见列举文件(Python SDK V2)

# ...

# 关键代码:添加start_after参数
for page in paginator.iter_page(oss.ListObjectsV2Request(
    bucket=args.bucket,
    start_after="images/cat.jpg",  # 从指定文件后开始
)):

# ...

Go

完整代码示例请参见列举文件(Go SDK V2)

// ...

// 关键代码:设置起始位置
request := &oss.ListObjectsV2Request{
    Bucket:     oss.Ptr(bucketName),
    StartAfter: oss.Ptr("images/cat.jpg"),  // 从指定文件后开始
}

// ...

PHP

完整代码示例请参见列举文件(PHP SDK V2)

// ...
// 关键代码:设置起始位置
$paginator = new Oss\Paginator\ListObjectsV2Paginator(client: $client);
$iter = $paginator->iterPage(new Oss\Models\ListObjectsV2Request(
bucket: $bucket,
startAfter:"images/cat.jpg", // 指定列举对象的起始位置
));
// ...

Ruby

完整代码示例请参见列举文件

# ...

# 关键代码:设置marker(起始位置)
objects = bucket.list_objects(:marker => 'images/cat.jpg')  # 从指定文件后开始

# ...

Android

完整代码示例请参见列举文件

// ...

// 关键代码:设置marker(起始位置)
ListObjectsRequest request = new ListObjectsRequest("examplebucket");
request.setMarker("images/cat.jpg");  // 从指定文件后开始

// ...

C++

完整代码示例请参见列举文件

// ...

// 关键代码:设置marker(起始位置)
ListObjectsRequest request(BucketName);
request.setMarker("images/cat.jpg");  // 从指定文件后开始

// ...

iOS

完整代码示例请参见列举文件

// ...

// 关键代码:设置marker(起始位置)
getBucket.marker = @"images/cat.jpg";  // 从指定文件后开始

// ...

C

完整代码示例请参见列举文件

// ...

// 关键代码:设置marker(起始位置)
char *nextMarker = "images/cat.jpg";  // 从指定文件后开始
aos_str_set(&params->marker, nextMarker);

// ...

使用ossutil

以下示例展示了如何列举存储空间examplebucket中指从test.txt之后的Object的信息。

ossutil api list-objects-v2 --bucket examplebucket --start-after test.txt

更多用法见list-objects-v2(get-bucket-v2)

输出结果示例:

假设Bucket中有:

images/cat.jpg
images/dog.png
images/archive/old.zip
readme.txt

当请求设置为 start_after="images/cat.jpg" 时,输出结果将不包含"images/cat.jpg"及按字母序排在它之前的所有文件:

images/dog.png
readme.txt

调整每页文件数量

MaxKey参数控制单次请求返回的文件数量。默认值为100,最大值为1000。

使用SDK

Java

完整代码示例请参见列举文件(Java SDK)

// ...

// 关键代码:添加max_keys参数设置每页文件数量
ListObjectsV2Request listObjectsV2Request = new ListObjectsV2Request(bucketName);
listObjectsV2Request.setMaxKeys(1000);  // 每页最多1000个文件
ListObjectsV2Result result = ossClient.listObjectsV2(listObjectsV2Request);

// ...

Python

完整代码示例请参见列举文件(Python SDK V2)

# ...

# 关键代码:添加max_keys参数设置每页文件数量
for page in paginator.iter_page(oss.ListObjectsV2Request(
    bucket=args.bucket,
    max_keys=1000,  # 每页最多1000个文件
)):

# ...

Go

完整代码示例请参见列举文件(Go SDK V2)

// ...

// 关键代码:添加max_keys参数设置每页文件数量
request := &oss.ListObjectsV2Request{
    Bucket:  oss.Ptr(bucketName),
    MaxKeys: 1000,  // 每页最多1000个文件
}

// ...

PHP

完整代码示例请参见列举文件(PHP SDK V2)

// ...

// 关键代码:创建分页器,并通过 maxKeys 参数设置每页返回的最大文件数量
$paginator = new Oss\Paginator\ListObjectsV2Paginator(client: $client);
$iter = $paginator->iterPage(new Oss\Models\ListObjectsV2Request(
                bucket: $bucket,
                maxKeys: 10, //每次列举返回的最大对象数量
            ));

// ...

Node.js

完整代码示例请参见列举文件(Node.js)

// ...

// 关键代码:添加max_keys参数设置每页文件数量
const result = await client.listV2({
    "max-keys": 1000  // 每页最多1000个文件
});

// ...

Android

完整代码示例请参见列举文件

// ...

// 关键代码:添加max_keys参数设置每页文件数量
ListObjectsRequest request = new ListObjectsRequest("examplebucket");
request.setMaxKeys(1000);  // 每页最多1000个文件

// ...

C++

完整代码示例请参见列举文件

// ...

// 关键代码:添加max_keys参数设置每页文件数量
ListObjectsRequest request(BucketName);
request.setMaxKeys(1000);  // 每页最多1000个文件

// ...

iOS

完整代码示例请参见列举文件

// ...

// 关键代码:添加max_keys参数设置每页文件数量
getBucket.maxKeys = 1000;  // 每页最多1000个文件

// ...

C

完整代码示例请参见列举文件

// ...

// 关键代码:添加max_keys参数设置每页文件数量
params->max_ret = 1000;  // 每页最多1000个文件

// ...

使用ossutil

以下示例展示了如何列举存储空间examplebucket中指定前缀dir下,前100Object的信息。

ossutil api list-objects-v2 --bucket examplebucket --prefix dir/ --max-keys 100

更多用法见list-objects-v2(get-bucket-v2)

输出结果示例:

假设Bucket中有:

images/cat.jpg
images/dog.png
images/archive/old.zip
readme.txt
  • maxKeys设置为2,所有文件将以每页2个的形式分页返回。

    image

  • maxKeys设置为100,所有文件将以每页100个的形式分页返回。

    image

应用于生产

性能优化

  • 调大分页大小:将MaxKey设为1000,在网络条件良好时能显著减少API调用次数。但要注意内存使用,避免一次性加载过多数据。

  • 并行分片处理:如果文件数量达到几十万甚至更多,单纯按顺序列举会很慢。这时可以按目录分别处理,比如同时处理images/、documents/、logs/等不同目录,能提升列举速度。

  • 缓存目录结构:对于不常变化的目录结构,可以缓存列举结果,减少重复调用。

成本控制

  • 避免频繁全量扫描:定期全量列举成本较高,优先考虑以下替代方案:

    • 若需定期生成完整的对象清单文件,请使用成本更低的存储空间清单功能,成本更低,适合周期性的全量分析。

    • 若需实时响应文件上传或删除,应使用事件通知,避免通过列举的方式,效率更高且成本更低。

  • 合理设置分页:过小的分页会增加API调用次数,过大的分页会增加单次请求的处理时间和内存消耗。

配额与限制

  • 单次返回上限:最多返回1000个文件。

  • 排序方式:仅支持按文件名字母序排序

常见问题

OSS是否支持列举指定页数的文件?

不支持。

如何列举指定目录下所有文件?

您可以使用命令行工具ossutil2.0的命令list-objects-v2(get-bucket-v2)列举指定目录下的所有文件信息,包括文件目录结构和文件名称等。

列举文件时是否支持按文件最后一次修改时间进行排序?

不支持。如果您需要按照文件最后一次修改时间进行排序,建议使用数据索引功能。