我尝试将大文件(4Gb)上传到Azure Blob存储,但它失败了。 根据这篇文章(https://docs.microsoft.com/en-us/azure/storage/storage-dotnet-how-to-use-blobs),这是我的代码:
CloudBlobContainer blobContainer = blobClient.GetContainerReference("my-container-name");
blobContainer.CreateIfNotExistsAsync().Wait();
CloudBlockBlob blockBlob = blobContainer.GetBlockBlobReference("blob-name");
await blockBlob.UploadFromFileAsync("C:\test.avi");
但是我收到了此错误
消息:流太长了 来源:System.Private.CoreLib
StackTrace:在System.IO.MemoryStream.Write(Byte []缓冲区,Int32 offset,Int32 count)at Microsoft.WindowsAzure.Storage.Blob.BlobWriteStream.d__5.MoveNext() 在C:\ Program Files中 (86)\詹金斯\工作空间\ release_dotnet_master \ LIB \ WindowsRuntime \斑点\ BlobWriteStream.cs:线 144 ---从抛出异常的先前位置开始的堆栈跟踪结束--- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务) System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务) Microsoft.WindowsAzure.Storage.Core.Util.StreamExtensions.d__1`1.MoveNext() 在C:\ Program Files中 (86)\詹金斯\工作空间\ release_dotnet_master \ LIB \普通\核心\的Util \ StreamExtensions.cs:线 308 ---从抛出异常的先前位置开始的堆栈跟踪结束--- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务) System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务) Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob<> c__DisplayClass20_0< b__0> d.MoveNext() 在C:\ Program Files中 (86)\詹金斯\工作空间\ release_dotnet_master \ LIB \ WindowsRuntime \斑点\ CloudBlockBlob.cs:线 301 ---从抛出异常的先前位置开始的堆栈跟踪结束--- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务) System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务) Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob<> c__DisplayClass23_0< b__0> d.MoveNext() 在C:\ Program Files中 (86)\詹金斯\工作空间\ release_dotnet_master \ LIB \ WindowsRuntime \斑点\ CloudBlockBlob.cs:线 397 ---从抛出异常的先前位置开始的堆栈跟踪结束--- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务) System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在System.Runtime.CompilerServices.TaskAwaiter.GetResult()
在 MyCompany.AzureServices.Blob.BlobService.d__7.MoveNext() 在C:\ MyProjectSource \ MyCompany.AzureServices \ Blob \ BlobService.cs:line 79 ---从抛出异常的先前位置开始的堆栈跟踪结束--- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务) System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在System.Runtime.CompilerServices.TaskAwaiter.GetResult()
在 MyCompany.AzureServices.Blob.MyProject.RecordBlobService<> c__DisplayClass1_0< b__0> d.MoveNext() 在 C:\ MyProjectSource \ MyCompany.AzureServices \斑点\ MyProject的\ RecordBlobService.cs:行 25
根据这篇文章(https://www.simple-talk.com/cloud/platform-as-a-service/azure-blob-storage-part-4-uploading-large-blobs/),我尝试为大文件添加更多选项。 这是我的新代码:
TimeSpan backOffPeriod = TimeSpan.FromSeconds(2);
int retryCount = 1;
BlobRequestOptions bro = new BlobRequestOptions()
{
//If the file to upload is more than 67Mo, we send it in multiple parts
SingleBlobUploadThresholdInBytes = 67108864, //67Mo (maximum)
//Number of threads used to send data
ParallelOperationThreadCount = 1,
//If the block fail, we retry once (retryCount) after 2 seconds (backOffPeriod)
RetryPolicy = new ExponentialRetry(backOffPeriod, retryCount),
};
blobClient.DefaultRequestOptions = bro;
CloudBlockBlob blockBlob = blobContainer.GetBlockBlobReference("blob-name");
//If the file is sended in multiple parts, theses parts size are 4Mo
blockBlob.StreamWriteSizeInBytes = 4194304; //4Mo (maximum)
await blockBlob.UploadFromFileAsync("C:\test.avi");
但我又遇到了同样的错误(Stream太长了)。
我在Microsoft.WindowsAzure.Storage库中找到了该函数" UploadFromFileAsync"使用" UploadFromStreamAsync"它使用MemoryStream。我认为我的错误来自于MemoryStream,但它在blob存储文章中写道,blob的最大大小为195Gb。那我怎么想用呢?我使用的是Microsoft.WindowsAzure.Storage版本7.2.1
谢谢!
更新1:感谢Tom Sun和Zhaoxing Lu,我尝试使用Microsoft.Azure.Storage.DataMovement。
可悲的是,我在" TransferManager.UploadAsync"上收到错误。功能。我试着谷歌但没什么......
有任何想法吗 ?
这是我的代码:
string storageConnectionString = "myStorageConnectionString";
string filePath = @"C:\LargeFile.avi";
string blobName = "large_file.avi";
CloudStorageAccount account = CloudStorageAccount.Parse(storageConnectionString);
CloudBlobClient blobClient = account.CreateCloudBlobClient();
CloudBlobContainer blobContainer = blobClient.GetContainerReference("mycontainer");
blobContainer.CreateIfNotExists();
CloudBlockBlob destBlob = blobContainer.GetBlockBlobReference(blobName);
// Setup the number of the concurrent operations
TransferManager.Configurations.ParallelOperations = 64;
// Setup the transfer context and track the upload progress
var context = new SingleTransferContext();
UploadOptions uploadOptions = new UploadOptions
{
DestinationAccessCondition = AccessCondition.GenerateIfExistsCondition()
};
context.ProgressHandler = new Progress<TransferStatus>(progress =>
{
Console.WriteLine("Bytes uploaded: {0}", progress.BytesTransferred);
});
// Upload a local blob
TransferManager.UploadAsync(filePath, destBlob, uploadOptions, context, CancellationToken.None).Wait();
这是错误:
消息:发生一个或多个错误。 (传输失败:值的格式&#39; *&#39;无效..)
来源:System.Private.CoreLib
StackTrace:
at System.Threading.Tasks.Task.ThrowIfExceptional(Boolean includeTaskCanceledExceptions)at System.Threading.Tasks.Task.Wait(Int32 millisecondsTimeout, 取消语音取消语言) System.Threading.Tasks.Task.Wait()at MyCompany.AzureServices.Blob.BlobService.d__7.MoveNext() 在C:\ MyProjectSource \ MyCompany.AzureServices \ Blob \ BlobService.cs:line 96 ---从抛出异常的先前位置开始的堆栈跟踪结束--- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务) System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务)在System.Runtime.CompilerServices.TaskAwaiter.GetResult()
在 MyCompany.AzureServices.Blob.MyProject.RecordBlobService&LT;&GT; c__DisplayClass1_0&LT; b__0&GT; d.MoveNext() 在 C:\ MyProjectSource \ MyCompany.AzureServices \斑点\ MyProject的\ RecordBlobService.cs:行 25
内部例外:
消息:传输失败:值的格式&#39; *&#39;无效..
资料来源:Microsoft.WindowsAzure.Storage.DataMovement
StackTrace:
在 Microsoft.WindowsAzure.Storage.DataMovement.TransferScheduler.d__22.MoveNext() 在 C:\本地\詹金斯\工作\ DM_Hotfix \工作区\ LIB \ TransferScheduler.cs:行 214 ---从抛出异常的先前位置开始的堆栈跟踪结束--- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务) System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务) Microsoft.WindowsAzure.Storage.DataMovement.SingleObjectTransfer.d__7.MoveNext() 在 C:\本地\詹金斯\工作\ DM_Hotfix \工作区\ LIB \ TransferJobs \ SingleObjectTransfer.cs:行 226 ---从抛出异常的先前位置开始的堆栈跟踪结束--- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务) System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务) Microsoft.WindowsAzure.Storage.DataMovement.TransferManager.d__72.MoveNext() 在 C:\本地\詹金斯\工作\ DM_Hotfix \工作区\ LIB \ TransferManager.cs:行 1263
下一个内部异常:
消息:值的格式&#39; *&#39;无效。
资料来源:Microsoft.WindowsAzure.Storage.DataMovement
StackTrace:
在 Microsoft.WindowsAzure.Storage.DataMovement.TransferControllers.BlockBlobWriter.HandleFetchAttributesResult(例外 e)in C:\本地\詹金斯\工作\ DM_Hotfix \工作区\ LIB \ TransferControllers \ TransferWriters \ BlockBlobWriter.cs:行 196点 Microsoft.WindowsAzure.Storage.DataMovement.TransferControllers.BlockBlobWriter.d__18.MoveNext() 在 C:\本地\詹金斯\工作\ DM_Hotfix \工作区\ LIB \ TransferControllers \ TransferWriters \ BlockBlobWriter.cs:行 157 ---从抛出异常的先前位置开始的堆栈跟踪结束--- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务) System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务) Microsoft.WindowsAzure.Storage.DataMovement.TransferControllers.BlockBlobWriter.d__16.MoveNext() 在 C:\本地\詹金斯\工作\ DM_Hotfix \工作区\ LIB \ TransferControllers \ TransferWriters \ BlockBlobWriter.cs:行 83 ---从抛出异常的先前位置开始的堆栈跟踪结束--- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务) System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务) Microsoft.WindowsAzure.Storage.DataMovement.TransferControllers.SyncTransferController.d__13.MoveNext() 在 C:\本地\詹金斯\工作\ DM_Hotfix \工作区\ LIB \ TransferControllers \ SyncTransferController.cs:行 81 ---从抛出异常的先前位置开始的堆栈跟踪结束--- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务) System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务) Microsoft.WindowsAzure.Storage.DataMovement.TransferControllers.TransferControllerBase.d__33.MoveNext() 在 C:\本地\詹金斯\工作\ DM_Hotfix \工作区\ LIB \ TransferControllers \ TransferControllerBase.cs:行 178 ---从抛出异常的先前位置开始的堆栈跟踪结束--- at System.Runtime.CompilerServices.TaskAwaiter.ThrowForNonSuccess(任务 任务) System.Runtime.CompilerServices.TaskAwaiter.HandleNonSuccessAndDebuggerNotification(任务 任务) Microsoft.WindowsAzure.Storage.DataMovement.TransferScheduler.d__22.MoveNext() 在 C:\本地\詹金斯\工作\ DM_Hotfix \工作区\ LIB \ TransferScheduler.cs:行 208
最后一个内部异常:
消息:值的格式&#39; *&#39;无效。
资料来源:System.Net.Http
StackTrace:
at System.Net.Http.Headers.HttpHeaderParser.ParseValue(String value, 对象storeValue,Int32&amp;指数) System.Net.Http.Headers.EntityTagHeaderValue.Parse(String input)at at Microsoft.WindowsAzure.Storage.Shared.Protocol.RequestMessageExtensions.ApplyAccessCondition(StorageRequestMessage C:\ Program Files中的request,AccessCondition accessCondition) (86)\詹金斯\工作空间\ release_dotnet_master \ LIB \ WindowsRuntime \共享\协议\ RequestMessageExtensions.cs:线 125点 Microsoft.WindowsAzure.Storage.Blob.CloudBlob&LT;&GT; c__DisplayClass116_0.b__0(RESTCommand
1 cmd, Uri uri, UriQueryBuilder builder, HttpContent cnt, Nullable
1 C:\ Program Files中的serverTimeout,OperationContext ctx) (86)\詹金斯\工作空间\ release_dotnet_master \ LIB \ WindowsRuntime \斑点\ CloudBlob.cs:线 1206在 Microsoft.WindowsAzure.Storage.Core.Executor.Executor.d__4`1.MoveNext() 在C:\ Program Files中 (86)\詹金斯\工作空间\ release_dotnet_master \ LIB \ WindowsRuntime \核心\执行人\ Executor.cs:线 91
最后是我的project.json:
{
"version": "1.0.0-*",
"dependencies": {
"Microsoft.Azure.DocumentDB.Core": "0.1.0-preview",
"Microsoft.Azure.Storage.DataMovement": "0.4.1",
"Microsoft.IdentityModel.Protocols": "2.0.0",
"NETStandard.Library": "1.6.1",
"MyProject.Data.Entities": "1.0.0-*",
"MyProject.Settings": "1.0.0-*",
"WindowsAzure.Storage": "7.2.1"
},
"frameworks": {
"netcoreapp1.0": {
"imports": [
"dnxcore50",
"portable-net451+win8"
],
"dependencies": {
"Microsoft.NETCore.App": {
"type": "platform",
"version": "1.0.0-*"
}
}
}
}
}
感谢您的帮助!
更新2(工作)
感谢Tom Sun,这是工作代码
string storageConnectionString = "myStorageConnectionString";
CloudStorageAccount account = CloudStorageAccount.Parse(storageConnectionString);
CloudBlobClient blobClient = account.CreateCloudBlobClient();
CloudBlobContainer blobContainer = blobClient.GetContainerReference("mycontainer");
blobContainer.CreateIfNotExistsAsync().Wait();
string sourcePath = @"C:\Tom\TestLargeFile.zip";
CloudBlockBlob destBlob = blobContainer.GetBlockBlobReference("LargeFile.zip");
// Setup the number of the concurrent operations
TransferManager.Configurations.ParallelOperations = 64;
// Setup the transfer context and track the upoload progress
var context = new SingleTransferContext
{
ProgressHandler =
new Progress<TransferStatus>(
progress => { Console.WriteLine("Bytes uploaded: {0}", progress.BytesTransferred); })
};
// Upload a local blob
TransferManager.UploadAsync(sourcePath, destBlob, null, context, CancellationToken.None).Wait();
Console.WriteLine("Upload finished !");
Console.ReadKey();
我也添加了
ShouldOverwriteCallback = (source, destination) =>
{
return true;
},
在SingleTransferContext
中覆盖blob(如果已存在)。
答案 0 :(得分:2)
我们可以使用Azure Storage Data Movement Library easily将大型文件上传到Azure blob存储。它适用于我,请尝试使用以下代码。有关Azure存储数据移动库的更多信息,请参阅document:
string storageConnectionString = "storage connection string";
CloudStorageAccount account = CloudStorageAccount.Parse(storageConnectionString);
CloudBlobClient blobClient = account.CreateCloudBlobClient();
CloudBlobContainer blobContainer = blobClient.GetContainerReference("mycontainer");
blobContainer.CreateIfNotExists();
string sourcePath = @"C:\Tom\TestLargeFile.zip";
CloudBlockBlob destBlob = blobContainer.GetBlockBlobReference("LargeFile.zip");
// Setup the number of the concurrent operations
TransferManager.Configurations.ParallelOperations = 64;
// Setup the transfer context and track the upoload progress
var context = new SingleTransferContext();
UploadOptions uploadOptions = new UploadOptions
{
DestinationAccessCondition = AccessCondition.GenerateIfExistsCondition()
};
context.ProgressHandler = new Progress<TransferStatus>(progress =>
{
Console.WriteLine("Bytes uploaded: {0}", progress.BytesTransferred);
});
// Upload a local blob
TransferManager.UploadAsync(sourcePath, destBlob, uploadOptions,context, CancellationToken.None).Wait();
SDK信息请参阅package.config文件
<?xml version="1.0" encoding="utf-8"?>
<packages>
<package id="Microsoft.Azure.KeyVault.Core" version="1.0.0" targetFramework="net452" />
<package id="Microsoft.Azure.Storage.DataMovement" version="0.4.1" targetFramework="net452" />
<package id="Microsoft.Data.Edm" version="5.6.4" targetFramework="net452" />
<package id="Microsoft.Data.OData" version="5.6.4" targetFramework="net452" />
<package id="Microsoft.Data.Services.Client" version="5.6.4" targetFramework="net452" />
<package id="Microsoft.WindowsAzure.ConfigurationManager" version="1.8.0.0" targetFramework="net452" />
<package id="Newtonsoft.Json" version="6.0.8" targetFramework="net452" />
<package id="System.Spatial" version="5.6.4" targetFramework="net452" />
<package id="WindowsAzure.Storage" version="7.2.1" targetFramework="net452" />
</packages>
从azure portal
检查上传的文件<强>更新强>
对于.net核心项目代码:
string storageConnectionString = "myStorageConnectionString";
CloudStorageAccount account = CloudStorageAccount.Parse(storageConnectionString);
CloudBlobClient blobClient = account.CreateCloudBlobClient();
CloudBlobContainer blobContainer = blobClient.GetContainerReference("mycontainer");
blobContainer.CreateIfNotExistsAsync().Wait();
string sourcePath = @"C:\Tom\TestLargeFile.zip";
CloudBlockBlob destBlob = blobContainer.GetBlockBlobReference("LargeFile.zip");
// Setup the number of the concurrent operations
TransferManager.Configurations.ParallelOperations = 64;
// Setup the transfer context and track the upoload progress
var context = new SingleTransferContext
{
ProgressHandler =
new Progress<TransferStatus>(
progress => { Console.WriteLine("Bytes uploaded: {0}", progress.BytesTransferred); })
};
// Upload a local blob
TransferManager.UploadAsync(sourcePath, destBlob, null, context, CancellationToken.None).Wait();
Console.WriteLine("Upload finished !");
Console.ReadKey();
答案 1 :(得分:1)
我们正在积极研究Azure存储客户端库中的问题。
请注意,由于UploadFromFileAsync()对于大量blob来说不是一个可靠而有效的操作,我建议您考虑以下备选方案:
如果您可以接受命令行工具,则可以尝试AzCopy,它能够以高性能传输Azure存储数据,并且可以暂停传输和传输。恢复。
如果您想以编程方式控制转移作业,请使用Azure Storage Data Movement Library,这是AzCopy的核心。
答案 2 :(得分:0)
原始问题已在WindowsAzure.Storage版本8.0中修复。