使用 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"
我正在使用以下代码将视频上传到 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"