我有一个相当简单的方法,它使用NEW Storage API创建SAS并将blob从一个容器复制到另一个容器。
我正在尝试使用它来复制blob BETWEEN STORAGE帐户。所以我有两个存储帐户,具有完全相同的容器,我正在尝试将存储帐户的容器中的blob复制到另一个存储帐户的容器。
我不知道SDK是否是为此而构建的,但似乎这是一种常见的情况。
其他一些信息:
我应该提到403是一个未经授权的结果http错误代码。
private static string CreateSharedAccessToken(CloudBlobClient blobClient, string containerName)
{
var container = blobClient.GetContainerReference(containerName);
var blobPermissions = new BlobContainerPermissions();
// The shared access policy provides read/write access to the container for 10 hours:
blobPermissions.SharedAccessPolicies.Add("SolutionPolicy", new SharedAccessBlobPolicy()
{
// To ensure SAS is valid immediately we don’t set start time
// so we can avoid failures caused by small clock differences:
SharedAccessExpiryTime = DateTime.UtcNow.AddHours(1),
Permissions = SharedAccessBlobPermissions.Write |
SharedAccessBlobPermissions.Read
});
blobPermissions.PublicAccess = BlobContainerPublicAccessType.Blob;
container.SetPermissions(blobPermissions);
return container.GetSharedAccessSignature(new SharedAccessBlobPolicy(), "SolutionPolicy");
}
在线下我使用此标记来调用复制操作,该操作返回403:
var uri = new Uri(srcBlob.Uri.AbsoluteUri + blobToken);
destBlob.StartCopyFromBlob(uri);
我的Azure.Storage版本是2.1.0.2。
如果有帮助,这是完整的复制方法:
private static void CopyBlobs(
CloudBlobContainer srcContainer, string blobToken,
CloudBlobContainer destContainer)
{
var srcBlobList
= srcContainer.ListBlobs(string.Empty, true, BlobListingDetails.All); // set to none in prod (4perf)
//// get the SAS token to use for all blobs
//string token = srcContainer.GetSharedAccessSignature(
// new SharedAccessBlobPolicy(), "SolutionPolicy");
bool pendingCopy = true;
foreach (var src in srcBlobList)
{
var srcBlob = src as ICloudBlob;
// Determine BlobType:
ICloudBlob destBlob;
if (srcBlob.Properties.BlobType == BlobType.BlockBlob)
{
destBlob = destContainer.GetBlockBlobReference(srcBlob.Name);
}
else
{
destBlob = destContainer.GetPageBlobReference(srcBlob.Name);
}
// Determine Copy State:
if (destBlob.CopyState != null)
{
switch (destBlob.CopyState.Status)
{
case CopyStatus.Failed:
log.Info(destBlob.CopyState);
break;
case CopyStatus.Aborted:
log.Info(destBlob.CopyState);
pendingCopy = true;
destBlob.StartCopyFromBlob(destBlob.CopyState.Source);
return;
case CopyStatus.Pending:
log.Info(destBlob.CopyState);
pendingCopy = true;
break;
}
}
// copy using only Policy ID:
var uri = new Uri(srcBlob.Uri.AbsoluteUri + blobToken);
destBlob.StartCopyFromBlob(uri);
//// copy using src blob as SAS
//var source = new Uri(srcBlob.Uri.AbsoluteUri + token);
//destBlob.StartCopyFromBlob(source);
}
}
最后是帐户和客户(审核)代码:
var credentials = new StorageCredentials("BAR", "FOO");
var account = new CloudStorageAccount(credentials, true);
var blobClient = account.CreateCloudBlobClient();
var sasToken = CreateSharedAccessToken(blobClient, "content");
当我使用REST客户端时,这似乎有用......任何想法?
答案 0 :(得分:1)
还要考虑这个问题:
var uri = new Uri(srcBlob.Uri.AbsoluteUri + blobToken);
可能你正在调用" ToString" Uri的方法,产生"人类可红色"网址的版本。如果blobToken包含特殊的字符,例如" +"这将导致存储服务器上出现令牌格式错误,拒绝为您提供访问权限。
请改用:
String uri = srcBlob.Uri.AbsoluteUri + blobToken;
答案 1 :(得分:0)
此任务不需要共享访问令牌。我最终得到了两个帐户并且工作正常:
var accountSrc = new CloudStorageAccount(credsSrc, true);
var accountDest = new CloudStorageAccount(credsSrc, true);
var blobClientSrc = accountSrc.CreateCloudBlobClient();
var blobClientDest = accountDest.CreateCloudBlobClient();
// Set permissions on the container.
var permissions = new BlobContainerPermissions {PublicAccess = BlobContainerPublicAccessType.Blob};
srcContainer.SetPermissions(permissions);
destContainer.SetPermissions(permissions);
//grab the blob
var sourceBlob = srcContainer.GetBlockBlobReference("FOO");
var destinationBlob = destContainer.GetBlockBlobReference("BAR");
//create a new blob
destinationBlob.StartCopyFromBlob(sourceBlob);
答案 2 :(得分:0)
由于两个CloudStorageAccount对象都指向同一个帐户,因此无需使用SAS令牌进行复制就可以正常工作了。
另一方面,您需要可从其他帐户复制的可公开访问的Blob或SAS令牌。所以你尝试的是正确的,但你建立了一个容器级访问策略,这可能需要30秒才能生效,这也在MSDN中有记录。在此间隔期间,与存储的访问策略关联的SAS令牌将失败,状态码为403(禁止),直到访问策略变为活动状态。
我想指出的另一件事是;当您调用Get * BlobReference来创建新的blob对象时,在您执行GET / HEAD操作(如FetchAttributes)之前,不会填充CopyState属性。