Azure Cloud storage SDK UploadFromStreamAsync not working
我正在尝试将文件上传到.Net Core 2.1中的Azure blob存储。以下是我的代码。
1 2 3 4 5 6 7 8 9 | IFormFileCollection files = formCollection.Files; foreach (var file in files) { if (file.Length > 0) { _azureCloudStorage.UploadContent(cloudBlobContainer, file.OpenReadStream(), file.FileName); } } |
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | public async void UploadContent(CloudBlobContainer containerReference, Stream contentStream, string blobName) { try { using (contentStream) { var blockBlobRef = containerReference.GetBlockBlobReference(blobName); //await containerReference.SetPermissionsAsync(new BlobContainerPermissions //{ // PublicAccess = BlobContainerPublicAccessType.Blob //}); await blockBlobRef.UploadFromStreamAsync(contentStream); } } catch(Exception ex) { //Error here } } |
代码执行时出现以下错误-
{System.ObjectDisposedException: Cannot access a closed file. at
System.IO.FileStream.get_Position() at
Microsoft.AspNetCore.WebUtilities.FileBufferingReadStream.get_Position()
at
Microsoft.AspNetCore.Http.Internal.ReferenceReadStream.VerifyPosition()
at
Microsoft.AspNetCore.Http.Internal.ReferenceReadStream.ReadAsync(Byte[]
buffer, Int32 offset, Int32 count, CancellationToken
cancellationToken) at
Microsoft.WindowsAzure.Storage.Core.Util.StreamExtensions.WriteToAsync[T](Stream
stream, Stream toStream, IBufferManager bufferManager, Nullable1 1 maxLength, Boolean calculateMd5,
copyLength, Nullable
ExecutionState1 executionState, StreamDescriptor streamCopyState, 1 length, AccessCondition accessCondition,
CancellationToken token) in C:\\Program Files
(x86)\\Jenkins\\workspace\
elease_dotnet_master\\Lib\\Common\\Core\\Util\\StreamExtensions.cs:line
301 at
Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.UploadFromStreamAsyncHelper(Stream
source, Nullable
BlobRequestOptions options, OperationContext operationContext,
IProgress1 progressHandler, CancellationToken cancellationToken) in 1 length, AccessCondition accessCondition,
C:\\Program Files
(x86)\\Jenkins\\workspace\
elease_dotnet_master\\Lib\\WindowsRuntime\\Blob\\CloudBlockBlob.cs:line
352 at
Microsoft.WindowsAzure.Storage.Blob.CloudBlockBlob.UploadFromStreamAsyncHelper(Stream
source, Nullable
BlobRequestOptions options, OperationContext operationContext,
CancellationToken cancellationToken) in C:\\Program Files
(x86)\\Jenkins\\workspace\
elease_dotnet_master\\Lib\\WindowsRuntime\\Blob\\CloudBlockBlob.cs:line
290 at Common.AzureCloudStorage.UploadContent(CloudBlobContainer
containerReference, Stream contentStream, String blobName)
对我有用的替代解决方案:使用流添加到天蓝色的blob存储中
对此有任何帮助吗?如果可以提供更多详细信息,请告诉我。
我的解决方案是包括文件长度并将位置设置为0。
1 2 3 4 | MemoryStream outStr = new MemoryStream(); CloudBlockBlob myBlob = container.GetBlockBlobReference(name); outStr.Position = 0; await myBlob.UploadFromStreamAsync(outStr, outStr.Length); |
几年后,出现相同问题(WindowsAzure.Storage版本3.0.3.0,targetFramework net45)。
Synchonous UploadFromStream有效,UploadFromStreamAsync不起作用。
我会投票怀疑Azure SDK不会磨练异步版本,而不是sdk使用不足。而且,我还是一位经验丰富的开发人员-经验丰富,不时会偶然发现已声明的Microsoft功能,但在仔细检查后无法使用。
对于其他异步方法(例如SetPropertiesAsync),此处也是如此。我一直在调试我的方法(如下),并且在每个* Async方法之后都失去了断点-这就是我弄清楚的方式。出于好奇,更改了UploadFromStreamAsync => UploadFromStream,然后将SetPropertiesAsync更改为SetProperties。
1 2 3 4 5 6 7 8 | public async Task StoreItem(string filename, MemoryStream content, string contentType, ICloudBlob cloudBlob) { cloudBlob.UploadFromStream(content); //this line works //await cloudBlob.UploadFromStreamAsync(content); //doesn't work cloudBlob.Properties.ContentType = contentType; cloudBlob.SetProperties(); //await cloudBlob.SetPropertiesAsync(); //doesn't work either } |
我的解决方案是等到任务完成后再继续,例如
1 2 3 4 5 6 7 8 9 10 | private async void SaveAsync(IFormFile file) { CloudBlockBlob blob = this.blobContainer.GetBlockBlobReference(file.FileName); var task = blob.UploadFromStreamAsync(file.OpenReadStream(), file.Length); while (task.IsCompleted == false) { Thread.Sleep(1000); } } |
也许传递长度也有帮助吗?
我已经测试了您的方法
我想您的问题可能是您收到的文件集合。
这是我的代码供您参考:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 | using ConsoleAppCore.DAL; using Microsoft.Azure.Storage; using Microsoft.Azure.Storage.Blob; using System; using System.IO; namespace ConsoleAppCore { class Program { static void Main(string[] args) { Run(); Console.WriteLine("Success"); Console.ReadLine(); } public static void Run() { CloudStorageAccount storageAccount = CloudStorageAccount.Parse("DefaultEndpointsProtocol=https;AccountName=xxxxx;AccountKey=O7xB6ebGq8e86XQSy2vkvSi/x/exxxxxxxxxxkly1DsQPYY5dF2JrAVHtBozbJo29ZrrGJA==;BlobEndpoint=https://xxxx.blob.core.windows.net/;QueueEndpoint=https://xxxx.queue.core.windows.net/;TableEndpoint=https://xxxx.table.core.windows.net/;FileEndpoint=https://xxxx.file.core.windows.net/;"); CloudBlobClient cloudBlobClient = storageAccount.CreateCloudBlobClient(); CloudBlobContainer container = cloudBlobClient.GetContainerReference("containertest"); container.CreateIfNotExists(); DirectoryInfo dir = new DirectoryInfo("E://Test"); foreach (FileInfo file in dir.GetFiles()) { BlobStorage.UploadContent(container, file.OpenRead(), file.Name); } } } } |
以及我的
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 | using Microsoft.Azure.Storage.Blob; using System; using System.Collections.Generic; using System.IO; using System.Text; namespace ConsoleAppCore.DAL { public class BlobStorage { public static async void UploadContent(CloudBlobContainer containerReference, Stream contentStream, string blobName) { try { using (contentStream) { var blockBlobRef = containerReference.GetBlockBlobReference(blobName); //await containerReference.SetPermissionsAsync(new BlobContainerPermissions //{ // PublicAccess = BlobContainerPublicAccessType.Blob //}); await blockBlobRef.UploadFromStreamAsync(contentStream); } } catch (Exception ex) { //Error here } } } } |