从ASP.NET上传到Azure blob的文件为空

时间:2017-12-02 14:31:54

标签: c# asp.net-mvc azure file-upload azure-storage

我不确定能解决什么问题。我正在开发一个简单的测试,即将图像上传到我的Azure存储。但是,该文件存在,但在存储上为null。看起来上传不起作用,我不明白为什么。我有这个控制器:

Create.cshtml.cs

namespace CoreWebApp.Pages
{
    public class CreateModel : PageModel
    {
        public void OnGet()
        {
        }

        [BindProperty]
        public CountryForm Country { get; set; }

        [HttpPost("CreateCountry")]
        public async Task<IActionResult> OnPostAsync(IFormFile file)
        {
            if (!ModelState.IsValid)
                return Page();

            /*var errors = ModelState.Where(x => x.Value.Errors.Count > 0)
                                    .Select(x => new { x.Key, x.Value.Errors })
                                    .ToArray();*/

            var filePath = Path.GetTempFileName();
            using (var stream = new FileStream(filePath, FileMode.Create))
            {
                await file.CopyToAsync(stream);

                string pictureUrl = Shared.AzureCloud.AzureCDN.GetAzureCDNInstance().UploadFile(stream, file.Name);
                try
                {
                    if (pictureUrl != null)
                        Shared.Database.SqlAction.CountriesTable.AddCountry(new Country()
                        {
                            Name = Country.Name,
                            PictureUrl = pictureUrl
                        });
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                }
            }

            return Page();
        }
    }
}

Create.cshtml

@page
@model CreateModel
@{
    ViewData["Title"] = "Create";    
}

<div class="container">
  <div class="row">
    <div class="col-lg-3" style="background-color:#FF0000;">
        <h4>Add a Country</h4>
        <form class="form form-horizontal" method="post" enctype="multipart/form-data" asp-controller="Create">
          <div asp-validation-summary="All"></div>
          <div class="row">
            <div class="col-md-12">
              <div class="form-group">
                <label asp-for="Country.Name" class="col-md-3 right">Name:</label>
                <div class="col-md-9">
                  <input asp-for="Country.Name" class="form-control" />
                  <span asp-validation-for="Country.Name"></span>
                </div>
              </div>
              <div class="form-group">
                <div class="col-md-10">
                    <p>Picture</p>
                    <input type="file" name="file" />
                </div>
              </div>
            </div>
          </div>
          <div class="row">
            <div class="col-md-12">
              <button type="submit">Create</button>
            </div>
          </div>
        </form>
    </div>
    <div class="col-*-*"></div>
  </div>
  <div class="row">
    <div class="col-*-*"></div>
    <div class="col-*-*"></div>
    <div class="col-*-*"></div>
  </div>
  <div class="row">
    ...
  </div>
</div>

我的AzureCDN类只是一个封装:

namespace Shared.AzureCloud
{
    public class AzureCDN
    {
        private CloudStorageAccount storageAccount { get; set; }
        private CloudBlobClient blobClient { get; set; }
        private CloudBlobContainer container { get; set; }
        private CloudBlockBlob blockBlob { get; set; }

        /// <summary>
        /// Initializes a new instance of the <see cref="T:Shared.AzureCloud.AzureCDN"/> class.
        /// </summary>
        public AzureCDN()
        {
            // Retrieve storage account from connection string.
            storageAccount = CloudStorageAccount.Parse(String.Format("DefaultEndpointsProtocol=https;AccountName={0};AccountKey={1}",
                                                                                         Shared.Constants.Azure.AccountName, Shared.Constants.Azure.AccountKey));
            // Create the blob client.
            blobClient = storageAccount.CreateCloudBlobClient();

            // Retrieve a reference to a container.
            container = blobClient.GetContainerReference("eyesmedias");

            // Create the container if it doesn't already exist.
            container.CreateIfNotExistsAsync();
        }

        /// <summary>
        /// Uploads the file.
        /// </summary>
        /// <returns>The file.</returns>
        /// <param name="fileStream">File stream.</param>
        /// <param name="fileName">File name.</param>
        public string UploadFile(FileStream fileStream, string fileName)
        {
            // Retrieve reference to a blob named {name}.
            blockBlob = container.GetBlockBlobReference(fileName);

            try
            {
                // Create or overwrite the {name} "blob with contents from a local file.
                blockBlob.UploadFromStreamAsync(fileStream);
                return (blockBlob.Uri.ToString());

            } catch (Exception e)
            {
                throw e;
            }
        }

        #region Singletown part

        /// <summary>
        /// The instance.
        /// </summary>
        private static AzureCDN Instance = null;

        /// <summary>
        /// Gets the azure CDN Instance.
        /// </summary>
        /// <returns>The azure CDNI nstance.</returns>
        public static AzureCDN GetAzureCDNInstance()
        {
            if (Instance == null)
            {
                Instance = new AzureCDN();
            }
            return (Instance);
        }

        /// <summary>
        /// Sets the azure CDN Instance.
        /// </summary>
        /// <param name="instance">Instance.</param>
        public static void SetAzureCDNInstance(AzureCDN instance)
        {
            Instance = instance;
        }

        /// <summary>
        /// Init this instance.
        /// </summary>
        public static void Init()
        {
            Instance = new AzureCDN();
        }

        #endregion
    }
}

问题是,blockBlob.UploadFromStreamAsync(fileStream);似乎没问题,因为它没有抛出任何异常并且路径被很好地返回,但是,即使文件在我的CDN上,它也是空的,不像文件我我在我的Mac上从ASP.NET页面中选择。

我是ASP.NET的新手(我在2天前开始),也欢迎从网络应用程序ASP.NET上传文件的建议:)

感谢您的帮助!

1 个答案:

答案 0 :(得分:1)

将文件复制到流后,您必须使用stream.Seek(0, SeekOrigin.Begin);再次将流的位置设置为开头(请参阅docs),以便上传实际内容:

        [HttpPost("CreateCountry")]
        public async Task<IActionResult> OnPostAsync(IFormFile file)
        {
            if (!ModelState.IsValid)
                return Page();

            /*var errors = ModelState.Where(x => x.Value.Errors.Count > 0)
                                    .Select(x => new { x.Key, x.Value.Errors })
                                    .ToArray();*/

            var filePath = Path.GetTempFileName();
            using (var stream = new FileStream(filePath, FileMode.Create))
            {
                await file.CopyToAsync(stream);

                stream.Seek(0, SeekOrigin.Begin); 

                string pictureUrl = Shared.AzureCloud.AzureCDN.GetAzureCDNInstance().UploadFile(stream, file.Name);
                try
                {
                    if (pictureUrl != null)
                        Shared.Database.SqlAction.CountriesTable.AddCountry(new Country()
                        {
                            Name = Country.Name,
                            PictureUrl = pictureUrl
                        });
                }
                catch (Exception e)
                {
                    Console.WriteLine(e);
                }
            }

            return Page();
        }

如果你不这样做,那么你要上传当前位置已经在最后的流,这样就会上传一个空文件。