Warning: file_get_contents(/data/phpspider/zhask/data//catemap/2/csharp/330.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
C# 在Azure存储客户端2.0中将一个Azure blob复制到另一个blob_C#_Azure_Azure Storage - Fatal编程技术网

C# 在Azure存储客户端2.0中将一个Azure blob复制到另一个blob

C# 在Azure存储客户端2.0中将一个Azure blob复制到另一个blob,c#,azure,azure-storage,C#,Azure,Azure Storage,在旧的1.7存储客户端中有一个CloudBlob.CopyFromBlob(otherBlob)方法,但在2.0版本中似乎没有。复制BLOB的推荐最佳实践是什么?我确实看到了ICloudBlob.BeginStartCopyFromBlob方法。如果这是合适的方法,我该如何使用它?已经写了一系列关于2.0版Azure存储的文章。我从他的博客文章for Blob Copy中摘录了这段代码 CloudStorageAccount storageAccount = new CloudStorageAc

在旧的1.7存储客户端中有一个CloudBlob.CopyFromBlob(otherBlob)方法,但在2.0版本中似乎没有。复制BLOB的推荐最佳实践是什么?我确实看到了ICloudBlob.BeginStartCopyFromBlob方法。如果这是合适的方法,我该如何使用它?

已经写了一系列关于2.0版Azure存储的文章。我从他的博客文章for Blob Copy中摘录了这段代码

CloudStorageAccount storageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);
CloudBlobClient cloudBlobClient = storageAccount.CreateCloudBlobClient();
CloudBlobContainer sourceContainer = cloudBlobClient.GetContainerReference(containerName);
CloudBlobContainer targetContainer = cloudBlobClient.GetContainerReference(targetContainerName);
string blobName = "<Blob Name e.g. myblob.txt>";
CloudBlockBlob sourceBlob = sourceContainer.GetBlockBlobReference(blobName);
CloudBlockBlob targetBlob = targetContainer.GetBlockBlobReference(blobName);
targetBlob.StartCopyFromBlob(sourceBlob);
CloudStorageAccount-storageAccount=new-CloudStorageAccount(new-StorageCredentials(accountName,accountKey),true);
CloudBlobClient CloudBlobClient=storageAccount.CreateCloudBlobClient();
CloudBlobContainer sourceContainer=cloudBlobClient.GetContainerReference(containerName);
CloudBlobContainer targetContainer=cloudBlobClient.GetContainerReference(targetContainerName);
字符串blobName=“”;
CloudBlockBlob sourceBlob=sourceContainer.GetBlockBlobReference(blobName);
CloudBlockBlob targetBlob=targetContainer.GetBlockBlobReference(blobName);
targetBlob.StartCopyFromBlob(sourceBlob);

Naveen已经解释了使用
StartCopyFromBlob
(同步方法)的正确语法。您提到的方法(
BeginStartCopyFromBlob
)是一种异步替代方法,可以与
任务
结合使用,例如:

    var blobClient = account.CreateCloudBlobClient();

    // Upload picture.
    var picturesContainer = blobClient.GetContainerReference("pictures");
    picturesContainer.CreateIfNotExists();
    var myPictureBlob = picturesContainer.GetBlockBlobReference("me.png");
    using (var fs = new FileStream(@"C:\Users\Public\Pictures\Sample Pictures\Chrysanthemum.jpg", FileMode.Open))
        myPictureBlob.UploadFromStream(fs);

    // Backup picture.
    var backupContainer = blobClient.GetContainerReference("backup");
    backupContainer.CreateIfNotExists();
    var backupBlob = picturesContainer.GetBlockBlobReference("me.png");

    var task = Task.Factory.FromAsync<string>(backupBlob.BeginStartCopyFromBlob(myPictureBlob, null, null), backupBlob.EndStartCopyFromBlob);
    task.ContinueWith((t) =>
    {
        if (!t.IsFaulted)
        {
            while (true)
            {
                Console.WriteLine("Copy state for {0}: {1}", backupBlob.Uri, backupBlob.CopyState.Status);
                Thread.Sleep(500);
            }
        }
        else
        {
            Console.WriteLine("Error: " + t.Exception);
        }
    });
var blobClient=account.CreateCloudBlobClient();
//上传图片。
var picturesContainer=blobClient.GetContainerReference(“图片”);
picturesContainer.CreateIfNotExists();
var myPictureBlob=picturesContainer.GetBlockBlobReference(“me.png”);
使用(var fs=newfilestream(@“C:\Users\Public\Pictures\Sample Pictures\jummy.jpg”,FileMode.Open))
myPictureBlob.UploadFromStream(fs);
//备份图片。
var backupContainer=blobClient.GetContainerReference(“备份”);
backupContainer.CreateIfNotExists();
var backupBlob=picturesContainer.GetBlockBlobReference(“me.png”);
var task=task.Factory.fromsync(backupBlob.begintartcopyfromblob(myPictureBlob,null,null),backupBlob.EndStartCopyFromBlob);
任务。继续((t)=>
{
如果(!t.IsFaulted)
{
while(true)
{
WriteLine(“复制状态为{0}:{1}”,backuplob.Uri,backuplob.CopyState.Status);
睡眠(500);
}
}
其他的
{
Console.WriteLine(“错误:+t.Exception”);
}
});
使用Storage 6.3(比原始问题中更新得多的库)和异步方法使用StartCoyAsync()


仅供参考,从最新版本(7.x)的
SDK
开始,由于
begintartcopyblob
功能不再存在,此功能不再有效

您可以这样做:

// this tunnels the data via your program,
// so it reuploads the blob instead of copying it on service side
using (var stream = await sourceBlob.OpenReadAsync())
{
  await destinationBlob.UploadFromStreamAsync(stream);
}
如@(Alexey Shcherbak)所述,这是一种更好的方式:


等待targetCloudBlob.startCopySync(sourceCloudBlob.Uri);
while(targetCloudBlob.CopyState.Status==CopyStatus.Pending)
{
等待任务。延迟(500);
//需要获取,否则“CopyState”将永远不会更新
等待targetCloudBlob.FetchAttributesAsync();
}
if(targetCloudBlob.CopyState.Status!=CopyStatus.Success)
{
抛出新异常(“复制失败:+targetCloudBlob.CopyState.Status”);
}

这是我的简单答案

public void Copy(CloudBlockBlob srcBlob, CloudBlobContainer destContainer)
{
    CloudBlockBlob destBlob;

    if (srcBlob == null)
    {
        throw new Exception("Source blob cannot be null.");
    }

    if (!destContainer.Exists())
    {
        throw new Exception("Destination container does not exist.");
    }

    //Copy source blob to destination container
    string name = srcBlob.Uri.Segments.Last();
    destBlob = destContainer.GetBlockBlobReference(name);
    destBlob.StartCopyAsync(srcBlob);                
}

对于我,WindowsAzure.Storage 8.0.1,James Hancock的解决方案执行了服务器端拷贝,但客户端拷贝状态一直处于
挂起状态(永远循环)。解决方案是在
Thread.sleep(500)
之后调用
targetCloudBlob
上的
FetchAttributes()


启动Azure Storage 8,要在存储帐户之间移动Blob,我使用类似于下面的代码,希望它能帮助某些人:

//copy blobs - from
CloudStorageAccount sourceStorageAccount = new CloudStorageAccount(new StorageCredentials(storageFromName, storageFromKey), true);
CloudBlobClient sourceCloudBlobClient = sourceStorageAccount.CreateCloudBlobClient();
CloudBlobContainer sourceContainer = sourceCloudBlobClient.GetContainerReference(containerFromName);

//copy blobs - to
CloudStorageAccount targetStorageAccount = new CloudStorageAccount(new StorageCredentials(storageToName, storageToKey), true);
CloudBlobClient targetCloudBlobClient = targetStorageAccount.CreateCloudBlobClient();
CloudBlobContainer targetContainer = targetCloudBlobClient.GetContainerReference(containerToName);

//create target container if didn't exists
try{
    await targetContainer.CreateIfNotExistsAsync();
}
catch(Exception e){
    log.Error(e.Message);
}

CloudBlockBlob sourceBlob = sourceContainer.GetBlockBlobReference(blobName);
CloudBlockBlob targetBlob = targetContainer.GetBlockBlobReference(blobName);

try{
    //initialize copying
    await targetBlob.StartCopyAsync(sourceBlob.Uri);
}
catch(Exception ex){
    log.Error(ex.Message);
    //return error, in my case HTTP
    return req.CreateResponse(HttpStatusCode.BadRequest, "Error, source BLOB probably has private access only: " +ex.Message);
} 

//fetch current attributes
targetBlob.FetchAttributes();

//waiting for completion
while (targetBlob.CopyState.Status == CopyStatus.Pending){
    log.Info("Status: " + targetBlob.CopyState.Status);
    Thread.Sleep(500);
    targetBlob.FetchAttributes();
}

//check status
if (targetBlob.CopyState.Status != CopyStatus.Success){
    //return error, in my case HTTP
    return req.CreateResponse(HttpStatusCode.BadRequest, "Copy failed with status: " + targetBlob.CopyState.Status);
}

//finally remove source in case Copy Status was Success
sourceBlob.Delete();

//and return success (in my case HTTP)
return req.CreateResponse(HttpStatusCode.OK, "Done.");

自从以前的帖子发布以来,API似乎已经被清理了一点

/\u客户端是通过构造函数中的DI注入的BlobServiceClient。
BlobContainerClient sourceContainerClient=\u client.GetBlobContainerClient(sourceContainerName);
BlobClient sourceClient=sourceContainerClient.GetBlobClient(blobName);
BlobContainerClient destContainerClient=\u client.GetBlobContainerClient(destContainerName);
BlobClient destClient=destContainerClient.GetBlobClient(blobName);
//假设如果下面的代码没有抛出异常,那么它是成功的。
CopyFromUriOperation操作=等待destClient.StartCopyFromUriSync(sourceClient.Uri);
等待操作。WaitForCompletionAsync();
operation.WaitForCompletionAsync
的文档说明:

定期调用服务器,直到长时间运行的操作完成。此方法将定期调用UpdateStatusAsync,直到HasCompleted为true,然后返回操作的最终结果


查看此方法的源代码似乎调用了
BlobBaseClient.GetProperties
(或异步版本),这将在出错时抛出
RequestFailureException

我正试图使用它在同一存储帐户内复制blob,但我得到了一个409冲突错误。消息是“blob类型对此操作无效”。我试着把它当作一个页面blob和一个块blob(我很确定我是一个页面blob)来解决它。结果表明,源是一个页面blob,但目标已作为块blob创建(在上次失败的尝试中)。删除目标并重试成功。这是服务器端副本吗?StartCopyFromBlob也是一个异步操作,因为这将重新上载blob。正如Aaron Sherman所提到的,对于较新的库,如果可以添加Vangaorth的FetchAttributes()修订内联,则应该使用StartCoyAsync,这可能会很有用-我在经过一段时间的调试后才看到。启动Windows Azure Storage 8.0时,还需要不断地获取属性(targetCloudBlob.FetchAttributes())。上面的代码段将由于超时而失败(无止境
// Aaron Sherman's code 

targetCloudBlob.StartCopy(sourceCloudBlob.Uri);

while (targetCloudBlob.CopyState.Status == CopyStatus.Pending)
{
    Thread.Sleep(500);
    targetCloudBlob.FetchAttributes();
}

// James Hancock's remaining code
//copy blobs - from
CloudStorageAccount sourceStorageAccount = new CloudStorageAccount(new StorageCredentials(storageFromName, storageFromKey), true);
CloudBlobClient sourceCloudBlobClient = sourceStorageAccount.CreateCloudBlobClient();
CloudBlobContainer sourceContainer = sourceCloudBlobClient.GetContainerReference(containerFromName);

//copy blobs - to
CloudStorageAccount targetStorageAccount = new CloudStorageAccount(new StorageCredentials(storageToName, storageToKey), true);
CloudBlobClient targetCloudBlobClient = targetStorageAccount.CreateCloudBlobClient();
CloudBlobContainer targetContainer = targetCloudBlobClient.GetContainerReference(containerToName);

//create target container if didn't exists
try{
    await targetContainer.CreateIfNotExistsAsync();
}
catch(Exception e){
    log.Error(e.Message);
}

CloudBlockBlob sourceBlob = sourceContainer.GetBlockBlobReference(blobName);
CloudBlockBlob targetBlob = targetContainer.GetBlockBlobReference(blobName);

try{
    //initialize copying
    await targetBlob.StartCopyAsync(sourceBlob.Uri);
}
catch(Exception ex){
    log.Error(ex.Message);
    //return error, in my case HTTP
    return req.CreateResponse(HttpStatusCode.BadRequest, "Error, source BLOB probably has private access only: " +ex.Message);
} 

//fetch current attributes
targetBlob.FetchAttributes();

//waiting for completion
while (targetBlob.CopyState.Status == CopyStatus.Pending){
    log.Info("Status: " + targetBlob.CopyState.Status);
    Thread.Sleep(500);
    targetBlob.FetchAttributes();
}

//check status
if (targetBlob.CopyState.Status != CopyStatus.Success){
    //return error, in my case HTTP
    return req.CreateResponse(HttpStatusCode.BadRequest, "Copy failed with status: " + targetBlob.CopyState.Status);
}

//finally remove source in case Copy Status was Success
sourceBlob.Delete();

//and return success (in my case HTTP)
return req.CreateResponse(HttpStatusCode.OK, "Done.");