【问题标题】:Uploaded file from ASP.NET to Azure blob is empty从 ASP.NET 上传到 Azure Blob 的文件为空
【发布时间】:2018-05-16 11:27:18
【问题描述】:

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

创建.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();
        }
    }
}

创建.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 天前开始的),也欢迎有关从 Web 应用程序 ASP.NET 上传文件的建议:)

感谢您的帮助!

【问题讨论】:

  • 您可以获取 1 兆字节的块,您可以单独或并行上传这些块。上传完所有块后,您将提交文件并将其拼接在 Azure Blob 存储中。查看 CloudBlockBlob.PutBlock 和 CloudBlockBlob.PutBlockList。如果您上传要嵌入 HTML 中的文件,最好使用内容类型。如果您希望文件的链接是下载链接,您不必这样做。虽然它永远不会受伤。 blockBlob.Properties.ContentType = "图像/JPEG"

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


【解决方案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();
        }

如果您不这样做,那么您将上传一个当前位置已经在末尾的流,因此将上传一个空文件。

【讨论】:

  • Whaaaaaaat 正因为如此 :( 我不知道流逻辑中的这个“位置”。它有效,非常感谢!
猜你喜欢
  • 2014-01-23
  • 2017-03-14
  • 1970-01-01
  • 2015-04-23
  • 2018-05-09
  • 1970-01-01
  • 1970-01-01
  • 2021-03-07
  • 2021-06-07
相关资源
最近更新 更多