2013-10-07 1 views
0

새 저장소 API를 사용하여 SAS를 만들고 한 컨테이너에서 다른 컨테이너로 BLOB를 복사하는 비교적 간단한 방법이 있습니다.Microsoft.WindowsAzure.Storage가있는 공유 액세스 토큰을 만듭니다. 403

저장 용량 계정간에 blob을 복사하는 데이 도구를 사용하려고합니다. 따라서 정확히 동일한 컨테이너를 사용하는 TWo Storage 계정이 있고 저장소 계정의 컨테이너에서 다른 저장소 계정의 컨테이너로 BLOB를 복사하려고합니다.

SDK가 내장되어 있는지 잘 모르겠지만 일반적인 시나리오처럼 보입니다.

몇 가지 추가 정보 :

  1. 나는 대상 컨테이너에 토큰을 생성합니다. 해당 토큰을 원본과 대상 모두에서 만들어야합니까? 토큰을 등록하는 데 시간이 걸립니까? 각 요청에 대해 또는 토큰 "수명"당 한 번만 생성해야합니까?

내가 언급해야 할 것은 승인되지 않은 결과 http 오류 코드입니다. Azure.Storage의 내 버전 2.1.0.2

var uri = new Uri(srcBlob.Uri.AbsoluteUri + blobToken); 
      destBlob.StartCopyFromBlob(uri); 

이다 : 나는 403 반환하는 복사 작업을 호출이 토큰을 사용하는 라인 아래

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"); 

    } 

.

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

은 얼마나 많은 시간을 당신은 SAS의 생성 및 복사의 URL의 사용 사이에 발생? – MikeWo

+0

즉시 발생합니다. SAS 메소드를 호출하고 나중에 밀리 초가 StartCopyFromBlob() API 호출을 호출합니다. uri를 인코딩하는 것과 관련이있을 수 있습니까? REST 클라이언트는 작동하지만 Azure SDK는 실패하지만 아무런 해결책도 발견하지 못했다는보고를 보았습니다. – nocarrier

+0

방금 ​​문제가 다른 두 계정간에 진행된다는 것을 깨달았습니다. 이는 두 계정 (대상 및 출처) 모두에 대해 creds가 필요하다는 것을 의미한다고 생각하십니까? SAS가 BLOB 콘텐츠 서버에서 어떻게 작동하는지 잘 모르겠다. – nocarrier

답변

0

이 작업에는 공유 액세스 토큰이 필요하지 않습니다. 나는 두 개의 계정을 끝내었고, 그것을 잘 작동합니다 : 두 CloudStorageAccount 객체가 동일한 계정을 가리 때문에 당신은 또한 언급 한 바와 같이하는 SAS 토큰없이 복사가 잘 작동 할

 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); 
+0

두 계정을 모두 소유하고 있다면 네가 한 것은 괜찮습니다. SAS를 사용하여 진행되는 작업에 대한 추측은 시계 드리프트였습니다. SAS를 만들었을 때 만료되었지만 시작이 아닙니다. 즉, 즉시 시작되었습니다. 서버의 시계가 서로 조금씩 어긋날 수 있으므로 SAS가 즉시 작동하지 않을 수도 있습니다. 대답은 과거 몇 분의 시작 시간으로 SAS를 만드는 것입니다. – MikeWo

0

.

반면에 다른 계정에서 복사하려면 공개적으로 액세스 가능한 BLOB 또는 SAS 토큰이 필요합니다. 그래서 당신이 시도한 것은 정확했지만 컨테이너 수준의 액세스 정책을 수립했습니다.이 정책은 3033 초까지 걸릴 수 있으며 MSDN에 문서화되어 있습니다. 이 간격 동안 액세스 정책이 활성화 될 때까지 저장된 액세스 정책과 연결된 SAS 토큰은 상태 코드 403 (금지됨)으로 실패합니다.

내가 지적하고 싶은 또 하나의 점은; Get * BlobReference를 호출하여 새 BLOB 객체를 만들면 FetchAttributes와 같은 GET/HEAD 작업을 수행 할 때까지 CopyState 속성이 채워지지 않습니다.

1

는이 문제를 고려 :

var uri = new Uri(srcBlob.Uri.AbsoluteUri + blobToken); 

은 아마 당신이 URL의 "인간 redable"버전을 생성 열린 우리당의 "ToString"방법을 요구하고있다.blobToken에 "+"와 같은 특수 문자가 포함되어 있으면 액세스를 거부하는 저장소 서버에서 토큰 형식 오류가 발생합니다.

사용이 대신은 :

String uri = srcBlob.Uri.AbsoluteUri + blobToken;