Все, что я нашел, это метод GET Bucket Но я не могу понять, как я могу получить только список папок в текущей папке. Какой префикс и разделитель мне нужно использовать? Это вообще возможно?
Amazon S3: как получить список папок в ведре?
Ответы (5)
В качестве примера предположим, что у меня есть корзина в области USEast1
с именем MyBucketName
со следующими ключами:
temp/
temp/foobar.txt
temp/txt/
temp/txt/test1.txt
temp/txt/test2.txt
temp2/
Работа с папками может сбивать с толку, потому что S3 изначально не поддерживает иерархическую структуру - скорее, это просто ключи, как и любой другой объект S3. Папки - это просто абстракция, доступная в веб-консоли S3, чтобы упростить навигацию по корзине. Поэтому, когда мы работаем программно, мы хотим найти ключи, соответствующие размерам «папки» (разделитель «/», размер = 0), потому что они, скорее всего, будут «папками», представленными нам консолью S3.
Примечание для обоих примеров: я использую пакет NuGet AWSSDK.S3 версии 3.1.
Пример 1. Все папки в корзине
Этот код изменен из этого базового примера в документации S3 на перечислить все ключи в ведре. В приведенном ниже примере будут идентифицированы все ключи, которые заканчиваются символом разделителя /
и также являются пустыми.
IAmazonS3 client;
using (client = new AmazonS3Client(Amazon.RegionEndpoint.USEast1))
{
// Build your request to list objects in the bucket
ListObjectsRequest request = new ListObjectsRequest
{
BucketName = "MyBucketName"
};
do
{
// Build your call out to S3 and store the response
ListObjectsResponse response = client.ListObjects(request);
// Filter through the response to find keys that:
// - end with the delimiter character '/'
// - are empty.
IEnumerable<S3Object> folders = response.S3Objects.Where(x =>
x.Key.EndsWith(@"/") && x.Size == 0);
// Do something with your output keys. For this example, we write to the console.
folders.ToList().ForEach(x => System.Console.WriteLine(x.Key));
// If the response is truncated, we'll make another request
// and pull the next batch of keys
if (response.IsTruncated)
{
request.Marker = response.NextMarker;
}
else
{
request = null;
}
} while (request != null);
}
Ожидаемый вывод на консоль:
temp/
temp/txt/
temp2/
Пример 2. Папки, соответствующие указанному префиксу
Вы можете дополнительно ограничить это, чтобы получать только папки, соответствующие указанному Prefix
, установив свойство Prefix
в ListObjectsRequest.
ListObjectsRequest request = new ListObjectsRequest
{
BucketName = "MyBucketName",
Prefix = "temp/"
};
Применительно к примеру 1 мы ожидаем следующий результат:
temp/
temp/txt/
Дополнительная литература:
request.Delimiter
не является необходимым и может вызывать проблемы, попробуйте без этого. Интересно, что BF/Music/
, кажется, сразу пропускают; не могли бы вы выполнить проверку работоспособности и убедиться, что он существует, как вы ожидаете, в ведре S3? Что касается подкаталогов, если они вам не нужны, вы можете просто отфильтровать свой список дальше после извлечения с помощью регулярного выражения или сопоставления с одной косой чертой и т. Д.
- person Anthony Neace; 05.11.2015
Используя prefix
из the/path/to/read/
(обратите внимание, что нет ведущей косой черты, но есть замыкающая косая черта) и delimiter
из /
, вы найдете все папки в этой папке внутри <CommonPrefixes>
.
CommonPrefixes
Ответ может содержать
CommonPrefixes
, только если вы укажете разделитель. Когда вы это сделаете,CommonPrefixes
будет содержать все (если есть) ключи между префиксом и следующим вхождением строки, указанной разделителем. Фактически CommonPrefixes перечисляет ключи, которые действуют как подкаталоги в каталоге, указанномPrefix
. Например, если префикс - это примечания /, а разделитель - это косая черта (/), в примечаниях / лето / июль общий префикс - ноты / лето /. Все ключи, объединенные в общий префикс, считаются одним возвратом при подсчете количества возвратов. См. MaxKeys.http://docs.aws.amazon.com/AmazonS3/latest/API/RESTBucketGET.html
В качестве альтернативы другой более простой подход - использовать https://github.com/minio/minio-dotnet.
Minio .Net реализует минимальные API для работы с Amazon S3 и другими совместимыми решениями для хранения данных.
В следующем примере показано, как можно отфильтровать только каталоги. Здесь CommonPrefix абстрагируется как папка через API ListObjects ().
using System;
using System.Collections.Generic;
using System.Linq;
using System.Text;
using System.Threading.Tasks;
using Minio;
using Minio.Xml;
namespace Minio.Examples
{
class ListObjects
{
static int Main(string[] args)
{
var client = new MinioClient("https://s3.amazonaws.com", "ACCESSKEY", "SECRETKEY");
var items = client.ListObjects("bucket");
foreach (Item item in items)
{
if (item.IsDir)
{
Console.Out.WriteLine("{0}", item.Key);
}
}
return 0;
}
}
}
Чего Энтони здесь не хватает, так это того, что папка не обязательно имеет связанный с ней ключ. Если файл создается в S3 и ему задан ключ вроде «folder / name.ext», S3 отобразит папку «folder», но у него нет ключа, что означает, что вы не получите его в своих результатах.
Единственный способ поймать эти папки - посмотреть на сами ключи и повторно выразить имя ключа для символа «/». Если бы я знал C # немного лучше, я бы написал вам образец кода, но для справки вот пример Python, который я написал по другому вопросу.
Добавление разделителя '/' к моим параметрам помогло мне.
Если кому-то нужно решение NodeJS, вот что я использовал:
listdelim: function (path) {
const params = {
Bucket: process.env['bucket'],
MaxKeys: 1000,
Prefix: path,
Delimiter: '/'
}
return new Promise((resolve, reject) => {
s3.listObjectsV2(params, function (err, data) {
if (err) {
console.log(err, err.stack)
reject(err)
} else {
resolve(data)
}
})
})
}