使用 Web 中的额外参数上传到 Azure Blob 存储 api

Uploading to Azure Blob Storage with extra parameters in Web api

我正在使用以下代码将视频上传到 Web 中的 blob Api,当我只上传视频时它工作正常。

    [HttpPost]
    [Route("api/v1/Video/upload")]
    public async Task<IHttpActionResult> PostPostVideo()
    {
        var Desc = HttpContext.Current.Request.Form["Desc"];
        if (!Request.Content.IsMimeMultipartContent("form-data"))
        {
            throw new HttpResponseException(HttpStatusCode.UnsupportedMediaType);
        }
        CloudStorageAccount _sourceStorageAccount = null;
        var accountName = ConfigurationManager.AppSettings["StorageAccountName"].ToString();
        var accountKey = ConfigurationManager.AppSettings["StorageAccountKey"].ToString();
        string Container = ConfigurationManager.AppSettings["VideoContainer"].ToString();

        _sourceStorageAccount = new CloudStorageAccount(new StorageCredentials(accountName, accountKey), true);

        CloudBlobClient blobClient = _sourceStorageAccount.CreateCloudBlobClient();

        CloudBlobContainer videoContainer = blobClient.GetContainerReference(Container);

        try
        {
            var provider = new AzureStorageMultipartFormDataStreamProvider(videoContainer);
            var filename = provider.FileData.FirstOrDefault().LocalFileName;
            return Ok("Video Uploaded Successfully");
        }
        catch (Exception ex)
        {
            return BadRequest("Some thing went Wrong" + ex);
        }
    }


   public class AzureStorageMultipartFormDataStreamProvider : 
   MultipartFormDataStreamProvider
   {
    private readonly CloudBlobContainer _blobContainer;
    private readonly string[] _supportedMimeTypes = { "video/mp4","video/mov" };

    public AzureStorageMultipartFormDataStreamProvider(CloudBlobContainer blobContainer)
        : base("azure")
    {
        _blobContainer = blobContainer;
    }

    public override Stream GetStream(HttpContent parent, HttpContentHeaders headers)
    {


            if (!_supportedMimeTypes.Contains(headers.ContentType.ToString().ToLower()))
            {
                throw new NotSupportedException("Only jpeg and png are supported");
            }

            // Generate a new filename for every new blob
            var fileName = Guid.NewGuid().ToString();

            CloudBlockBlob blob = _blobContainer.GetBlockBlobReference(fileName + ".mp4");

            if (headers.ContentType != null)
            {
                // Set appropriate content type for your uploaded file
                blob.Properties.ContentType = headers.ContentType.MediaType;

            }

            this.FileData.Add(new MultipartFileData(headers, blob.Name));

            return blob.OpenWrite();
      }
  }

然而,当我尝试使用 PostMan 发送表单数据中的文本值时出现错误。

 System.IO.IOException: Error writing MIME multipart body part to output stream. ---> System.InvalidOperationException: The stream provider of type 'AzureStorageMultipartFormDataStreamProvider' threw an exception.

我知道 GetStream()AzureStorageMultipartFormDataStreamProvider class 中被多次调用。我不确定我是否遗漏了一些东西。

根据您的描述,我检查了您的代码,发现 txt 数据的 ContentType 为空,因此 _supportedMimeTypes.Contains(headers.ContentType.ToString().ToLower()) 会抛出异常,你可以调试你的代码来检查这个问题。

根据您的要求,您可以按如下方式更改 GetStream 方法:

public override Stream GetStream(HttpContent parent, HttpContentHeaders headers)
{
    // For form data, Content-Disposition header is a requirement
    ContentDispositionHeaderValue contentDisposition = headers.ContentDisposition;

    if (contentDisposition != null)
    {
        //file
        if (!String.IsNullOrEmpty(contentDisposition.FileName))
        {
            if (!_supportedMimeTypes.Contains(headers.ContentType.ToString().ToLower()))
            {
                throw new NotSupportedException("Only .mp4 and .mov are supported");
            }

            // Generate a new filename for every new blob
            var fileName = Guid.NewGuid().ToString();

            CloudBlockBlob blob = _blobContainer.GetBlockBlobReference(fileName + ".mp4");

            if (headers.ContentType != null)
            {
                // Set appropriate content type for your uploaded file
                blob.Properties.ContentType = headers.ContentType.MediaType;

            }

            this.FileData.Add(new MultipartFileData(headers, blob.Name));
            //I also define my AzureBlobMultipartFileData instead of MultipartFileData to show the BlobUrl
            //this._blobFileData.Add(new AzureBlobMultipartFileData(headers, blob.Uri.AbsoluteUri));

            return blob.OpenWrite();
        }
        else
            return new MemoryStream();

    }
    throw new InvalidOperationException("Did not find required 'Content-Disposition' header field in MIME multipart body part..");
}

此外,为了提取txt内容,您还需要覆盖AzureStorageMultipartFormDataStreamProvider下的ExecutePostProcessingAsync方法,如下所示:

    /// <summary>
    /// Read the non-file contents as form data.
    /// </summary>
    /// <returns></returns>
    public override async Task ExecutePostProcessingAsync()
    {
        for (int index = 0; index < Contents.Count; index++)
        {
            HttpContent formContent = Contents[index];
            ContentDispositionHeaderValue contentDisposition = formContent.Headers.ContentDisposition;
            if (String.IsNullOrEmpty(contentDisposition.FileName))
            {
                string formFieldName = contentDisposition.Name.Trim('\"');
                string formFieldValue = await formContent.ReadAsStringAsync();
                FormData.Add(formFieldName, formFieldValue);
            }
        }
    }

您的操作,在构建AzureStorageMultipartFormDataStreamProvider后,您需要手动读取如下内容:

var provider = new AzureStorageMultipartFormDataStreamProvider(container);

await Request.Content.ReadAsMultipartAsync(provider);

我只是return回复如下:

return Request.CreateResponse(HttpStatusCode.OK, new
{
    fileData = provider.BlobFileData.Select(f => f.BlobUrl),
    formData = provider.FormData.AllKeys.Select(d => new { key = d, value = provider.FormData[d] })
}, "application/json");

测试:

更新:

要从 MIME 类型中检索文件扩展名,您可以按如下方式利用 MimeTypeMap

Console.WriteLine("audio/wav -> " + MimeTypeMap.GetExtension("audio/wav")); // ".wav"