我正在尝试确定我的 Amazon S3 存储桶上是否存在某个文件夹,如果不存在,我想创建它。
目前我可以使用 .NET SDK 创建文件夹,如下所示:
public void CreateFolder(string bucketName, string folderName)
{
var folderKey = folderName + "/"; //end the folder name with "/"
var request = new PutObjectRequest();
request.WithBucketName(bucketName);
request.StorageClass = S3StorageClass.Standard;
request.ServerSideEncryptionMethod = ServerSideEncryptionMethod.None;
//request.CannedACL = S3CannedACL.BucketOwnerFullControl;
request.WithKey(folderKey);
request.WithContentBody(string.Empty);
S3Response response = m_S3Client.PutObject(request);
}
现在,当我尝试使用此代码查看该文件夹是否存在时:
public bool DoesFolderExist(string key, string bucketName)
{
try
{
S3Response response = m_S3Client.GetObjectMetadata(new GetObjectMetadataRequest()
.WithBucketName(bucketName)
.WithKey(key));
return true;
}
catch (Amazon.S3.AmazonS3Exception ex)
{
if (ex.StatusCode == System.Net.HttpStatusCode.NotFound)
return false;
//status wasn't not found, so throw the exception
throw;
}
}
找不到该文件夹。奇怪的是,如果我使用 AWS 管理控制台创建文件夹,“DoesFolderExist”方法可以看到它。
我不确定这是否是 ACL/IAM 的问题,但不确定如何解决此问题。
您的代码实际上对我有用,但有一些事情您需要注意。
据我了解,Amazon S3 没有文件夹的概念,但各个客户端可能会像显示文件夹一样显示 S3 对象。因此,如果您创建一个名为 A/B 的对象,那么客户端可能会显示它,就好像它是名为 A 的文件夹内名为 B 的对象一样。这很直观,似乎已成为标准,但模拟空文件夹不会出现有一个标准。
例如,我使用你的方法创建了一个名为 Test 的文件夹,然后实际上最终创建了一个名为 Test/ 的对象。但我在 AWS Explorer(即 Visual Studio 的插件)中创建了一个名为 Test2 的文件夹,它最终创建了一个名为 Test2/Test2_$folder$ 的对象 (AWS Explorer 会将 Test 和 Test2 显示为文件夹)
这意味着您不需要在使用“文件夹”之前创建它,这可能意味着您不需要DoesFolderExist 方法。
正如我提到的,我尝试了您的代码,它可以工作并找到它创建的 Test 文件夹,但必须调整密钥才能找到由 AWS Explorer 创建的文件夹,即
DoesFolderExist("Test/" , bucketName); // Returns true
DoesFolderExist("Test2/" , bucketName); // Returns false
DoesFolderExist("Test2/Test2_$folder$", bucketName); // Returns true
因此,如果您仍然想要使用DoesFolderExist方法,那么仅查找以folderName +“/”开头的任何对象可能会更安全,即类似
ListObjectsRequest request = new ListObjectsRequest();
request.BucketName = bucketName ;
request.WithPrefix(folderName + "/");
request.MaxKeys = 1;
using (ListObjectsResponse response = m_S3Client.ListObjects(request))
{
return (response.S3Objects.Count > 0);
}
public async Task CreateFoldersAsync(string bucketName, string path)
{
path = path.EnsureEndsWith('/');
IAmazonS3 client =
new AmazonS3Client(YOUR.AccessKeyId, YOUR.SecretAccessKey,
RegionEndpoint.EUWest1);
var findFolderRequest = new ListObjectsV2Request();
findFolderRequest.BucketName = bucketName;
findFolderRequest.Prefix = path;
findFolderRequest.MaxKeys = 1;
ListObjectsV2Response findFolderResponse =
await client.ListObjectsV2Async(findFolderRequest);
if (findFolderResponse.S3Objects.Any())
{
return;
}
PutObjectRequest request = new PutObjectRequest()
{
BucketName = bucketName,
StorageClass = S3StorageClass.Standard,
ServerSideEncryptionMethod = ServerSideEncryptionMethod.None,
Key = path,
ContentBody = string.Empty
};
// add try catch in case you have exceptions shield/handling here
PutObjectResponse response = await client.PutObjectAsync(request);
}
ListObjectsRequest findFolderRequest = new ListObjectsRequest();
findFolderRequest.BucketName = bucketName;
findFolderRequest.Prefix = path;
ListObjectsResponse findFolderResponse = s3Client.ListObjects(findFolderRequest);
Boolean folderExists = findFolderResponse.S3Objects.Any();
路径可以是“images/40/”之类的东西。 使用上面的代码可以检查bucket下是否存在所谓的“images/40/”文件夹。
但是Amazon S3数据模型没有文件夹的概念。当您尝试将图像或文件复制到特定路径时,如果这个所谓的文件夹不存在,它将自动创建作为该文件或图像的键名的一部分。因此,你实际上不需要检查这个文件夹是否存在。
来自 docs.aws.amazon.com 的非常重要的信息:Amazon S3 数据模型是扁平结构:您创建一个存储桶,存储桶存储对象。没有子存储桶或子文件夹的层次结构;但是,您可以像 Amazon S3 控制台一样使用键名称前缀和分隔符来推断逻辑层次结构。
http://docs.aws.amazon.com/AmazonS3/latest/dev/UsingMetadata.html
using Amazon.S3.Transfer;
using Amazon.S3;
using Amazon;
using System;
using System.Linq;
using System.Threading.Tasks;
using System.IO;
using System.Configuration;
using Amazon.S3.Model;
namespace awss3Uploader
{
internal class Program
{
static readonly string bucketName = ConfigurationManager.AppSettings["S3_BucketName"];
static async Task Main(string[] args)
{
try
{
RegionEndpoint region = RegionEndpoint.GetBySystemName(ConfigurationManager.AppSettings["S3_RegionName"]);
var awsAccessKeyId = ConfigurationManager.AppSettings["S3_awsAccessKeyId"];
var awsSecretAccessKey = ConfigurationManager.AppSettings["S3_awsSecretAccessKey"];
var s3Client = new AmazonS3Client(awsAccessKeyId, awsSecretAccessKey, region);
await UploadFile(s3Client);
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException.Message);
Console.WriteLine(ex.StackTrace);
}
Console.ReadLine();
}
static async Task UploadFile(AmazonS3Client s3Client)
{
var localFolderPath = ConfigurationManager.AppSettings["S3_LocalUploadFolderPath"];
string remoteFolderPrefix = ConfigurationManager.AppSettings["S3_FolderPrefix"];
var fileTransferUtility = new TransferUtility(s3Client);
DirectoryInfo directoryInfo= new DirectoryInfo(localFolderPath);
var allLocalUploadFiles = directoryInfo.GetFiles();
if (allLocalUploadFiles.Count()<1)
{
Console.WriteLine($"No files to upload");
}
foreach (var item in allLocalUploadFiles)
{
Console.WriteLine($"Uploading file {item.Name}");
await fileTransferUtility.UploadAsync(item.FullName,bucketName, remoteFolderPrefix+"/"+item.Name);
Console.WriteLine($"File Uploaded");
Console.WriteLine($"File removing from local");
System.IO.File.Delete(item.FullName);
Console.WriteLine($"File removed from local");
}
var allFiles = s3Client.ListObjectsAsync(bucketName,remoteFolderPrefix+"/").Result.S3Objects;
Console.WriteLine($"Below files are available now, count {allFiles.Count}");
foreach (var file in allFiles)
{
Console.WriteLine(file.Key);
}
//DownloadS3Files(fileTransferUtility, localFolderPath+"TestS3\\");
Console.WriteLine("Press a key to exit..");
Console.ReadKey();
}
private static void DownloadS3Files(TransferUtility s3Transfer, string LocalFolderPath)
{
string remoteFolderPrefix = ConfigurationManager.AppSettings["S3_FolderPrefix"];
string bucketName = ConfigurationManager.AppSettings["S3_BucketName"];
var allFilesInS3 = s3Transfer.S3Client.ListObjects(bucketName, remoteFolderPrefix).S3Objects;
Console.WriteLine("S3 total files " + allFilesInS3.Count);
foreach (var file in allFilesInS3)
{
var fileNameparts = file.Key.Split('/');
var filename = fileNameparts[fileNameparts.Length - 1];
if (filename == string.Empty)
{
Console.WriteLine("S3 invalid file :" + file.Key);
continue;
}
Console.WriteLine("S3 downloading file :" + file.Key);
s3Transfer.Download(LocalFolderPath + filename, bucketName, file.Key);
Console.WriteLine("S3 download complete");
Console.WriteLine("S3 removing file :" + file.Key);
s3Transfer.S3Client.DeleteObject(bucketName, file.Key);
Console.WriteLine("S3 file removed");
}
}
public static bool DoesFolderExist(AmazonS3Client s3Client,string bucketName,string FolderPath)
{
ListObjectsRequest findFolderRequest = new ListObjectsRequest();
findFolderRequest.BucketName = bucketName;
findFolderRequest.Prefix = FolderPath;
ListObjectsResponse findFolderResponse = s3Client.ListObjects(findFolderRequest);
Boolean folderExists = findFolderResponse.S3Objects.Any();
return folderExists;
}
private static async Task ListBucketsAsync(AmazonS3Client s3Client)
{
var allBucket = s3Client.ListBucketsAsync().Result.Buckets;
foreach (var item in allBucket)
{
Console.WriteLine(item.BucketName);
try
{
var allFiles = s3Client.ListObjectsAsync(item.BucketName, "").Result.S3Objects;
foreach (var file in allFiles)
{
Console.WriteLine(file.Key);
}
}
catch (Exception ex)
{
Console.WriteLine(ex.InnerException.Message);
}
}
}
}
}