/// <summary> /// クラウド側でコピーを行う。 /// </summary> /// <param name="sourceFile">コピー元ファイル</param> /// <param name="destinationBlob">コピー先Blob</param> /// <param name="destinationFile">コピー先ファイル</param> /// <returns>成功:true 失敗:false</returns> public bool CopyOnServer(ArchiveFile sourceFile, Blob destinationBlob, ArchiveFile destinationFile) { CloudBlockBlob destinationBlockBlob = destinationBlob.ArchiveFileToBlob(destinationFile); CloudBlockBlob sourceBlockBlob = ArchiveFileToBlob(sourceFile); bool result = false; // 本来ならStartCopyAsync等の、ローカルへのDownloadを介さない処理を使いたいが, // StartCopyAsyncはストレージアカウントを跨ぐ場合、URIを参照するため、 // コピー元がpublic Accessでないと失敗する。 _polly.Execute( () => { var destContainer = destinationBlob.GetContainerReadOnly(destinationFile.ContainerName); destContainer.CreateIfNotExistsAsync().Wait(); // MSサポートに問い合わせたところ、 // StartCopyAsyncをWaitすることで完了まで待機してもらえるということなので、その前提で実装する。 destinationBlockBlob.StartCopyAsync(sourceBlockBlob).Wait(); _logger.Debug($"Copy result [{destinationBlockBlob.CopyState}] from [{sourceFile.ContainerName}/{sourceFile.FilePath}] to [{destinationFile.ContainerName}/{destinationFile.FilePath}] "); if (destinationBlockBlob.CopyState != null && destinationBlockBlob.CopyState.Status == CopyStatus.Success) { result = true; } }); return(result); }
/// <summary> /// 指定したコンテナとdirectory以下のBlob一覧とメタデータを取得する。 /// </summary> /// <param name="directory">ディレクトリ</param> /// <returns>ファイル一覧</returns> public IEnumerable <ArchiveFile> GetArchiveFiles(ArchiveDirectory directory) { _log.EnterJson("ArchiveDirectory: {0}", directory); Assert.IfNull(directory); CloudBlobContainer container = _collectingBlob.GetContainerReadOnly(directory.ContainerName ?? string.Empty); CloudBlobDirectory blobDirectory = container.GetDirectoryReference(directory.DirectoryPath); var blobs = new List <CloudBlockBlob>(); _polly.Execute( () => { var token = default(BlobContinuationToken); do { // Blob一覧を取得 BlobResultSegment segment = null; // 指定しない場合上限の5000件ずつ取得される segment = blobDirectory.ListBlobsSegmentedAsync(true, BlobListingDetails.Metadata, null, token, null, null).Result; token = segment.ContinuationToken; blobs.AddRange(segment.Results.OfType <CloudBlockBlob>()); }while (token != null); }); return(blobs.Select(blob => Blob.BlobToArchiveFile(blob))); }
/// <summary> /// ストレージアカウント間でファイルをコピーする /// </summary> /// <param name="sourceFile">コピー元</param> /// <param name="destinationBlob">コピー先Blob</param> /// <param name="destinationFile">コピー先ファイル</param> /// <exception cref="AggregateException">Result/Waitを使用しているため。詳細はinnerExceptionを参照</exception> public void Copy(ArchiveFile sourceFile, Blob destinationBlob, ArchiveFile destinationFile) { CloudBlockBlob destinationBlockBlob = destinationBlob.ArchiveFileToBlob(destinationFile); CloudBlockBlob sourceBlockBlob = ArchiveFileToBlob(sourceFile); // 本来ならStartCopyAsync等の、ローカルへのDownloadを介さない処理を使いたいが, // StartCopyAsyncはストレージアカウントを跨ぐ場合、URIを参照するため、 // コピー元がpublic Accessでないと失敗する。 // ・・と考えていたが、接続文字列に認証文字まで含めている場合問題ないようなのでこちらは使用しないようにする。 _polly.Execute( () => { var destContainer = destinationBlob.GetContainerReadOnly(destinationFile.ContainerName); destContainer.CreateIfNotExistsAsync().Wait(); using (var targetBlobStream = destinationBlockBlob.OpenWriteAsync().Result) using (var sourceBlobStream = sourceBlockBlob.OpenReadAsync().Result) { sourceBlobStream.CopyToAsync(targetBlobStream).Wait(); } }); }