关于c#:Azure云存储SDK UploadFromStreamAsync不起作用

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

UploadContent实现-

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
copyLength, Nullable
1 maxLength, Boolean calculateMd5,
ExecutionState1 executionState, StreamDescriptor streamCopyState,
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
1 length, AccessCondition accessCondition,
BlobRequestOptions options, OperationContext operationContext,
IProgress1 progressHandler, CancellationToken cancellationToken) in
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
1 length, AccessCondition accessCondition,
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);
        }

    }

也许传递长度也有帮助吗?


我已经测试了您的方法UploadContent,效果很好。

我想您的问题可能是您收到的文件集合。

这是我的代码供您参考:

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

            }
        }


    }
}

以及我的BlobStorage类中的UploadContent方法:

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
            }
        }
    }
}