它有什么作用?
总结一下代码的作用,这是一个分步说明:
- 通过HTTP POST上传在网络浏览器中提交的文件。
- 将文件转换为字节数组。
- 将文件数据保存到本地文件系统、CDN获取其他你想存储的地方。
它实际上是做什么的?
让我们更深入地看一下代码。
- Home控制器下的Index视图显示一个输入字段,用于选择要上传的文件,以及一个Submit按钮以完成上传过程。 这是一个片段:
<form enctype =“ multipart/form-data” method =“ post”>
...
<input multiple =“ multiple” name =“ files” type =“ file” />
...
<input type =“ submit” value =“上传” />
...
</ form>
- 接下来,Home控制器的Post方法处理上载的文件。它设置为循环浏览多个上传的文件,并分别上传每个文件。
[HttpPost("UploadFiles")]
//OPTION A: 禁用Asp.Net Core的默认上载大小限制
[DisableRequestSizeLimit]
//OPTION B: 取消注释以设置指定的上载文件限制
//[RequestSizeLimit(40000000)]
public async Task<IActionResult> Post(List<IFormFile> files)
{
var uploadSuccess = false;
string uploadedUri = null;
foreach (var file in files)
{
if (file.Length <= 0)
{
continue;
}
await using var memoryStream = new MemoryStream();
await file.CopyToAsync(memoryStream);
// OPTION A: CDN
//(uploadSuccess, uploadedUri) = await UploadToCDN(file.FileName, file.OpenReadStream());
// OPTION B: LocalStorage
(uploadSuccess, uploadedUri) = await UploadToLocalStorage(file.FileName, memoryStream);
TempData["uploadedUri"] = uploadedUri;
}
if (uploadSuccess)
return View("UploadSuccess");
else
return View("UploadError");
}
private async Task<(bool, string)> UploadToLocalStorage(string filename, MemoryStream stream = null)
{
if (stream == null)
{
return (false, null);
}
var rootPath = Path.Join(_env.ContentRootPath, FileUploadPath);
if (!Directory.Exists(rootPath)) Directory.CreateDirectory(rootPath);
var fileMd5 = BitConverter.ToString(System.Security.Cryptography.MD5.Create().ComputeHash(stream)).Replace("-", "");
var imageName = $"img_{DateTime.UtcNow:yyyy_MM_dd}_{fileMd5}{Path.GetExtension(filename)}";
var imageFullName = Path.Join(rootPath, imageName);
if (!System.IO.File.Exists(imageFullName))
{
await System.IO.File.WriteAllBytesAsync(imageFullName, stream.ToArray());
}
return (true, imageName);
}
private async Task<(bool, string)> UploadToCDN(string filename, Stream stream = null)
{
if (stream == null)
{
return (false, null);
}
using HttpContent content = new StreamContent(stream);
content.Headers.Add(FileType, Path.GetExtension(filename).ToUpper());
var client = _clientFactory.CreateClient(CDNClient);
var response = await client.PostAsync("UpLoadForByte.ashx", content);
if (response != null && response.IsSuccessStatusCode)
{
var responseStr = await response.Content.ReadAsStringAsync();
if (responseStr.Equals("Error", StringComparison.CurrentCultureIgnoreCase))
{
return (false, "CDN服务器异常");
}
return (true, responseStr.Replace("http:", "https:"));
}
else
{
return (false, $"CDN服务器请求失败,{response.StatusCode}");
}
}
然后我们测试结果如下: OPTION A:上传到CDN
OPTION B:存储到本地文件系统
关于CDN上传使用的是HttpClient,使用文档请参考 https://docs.microsoft.com/zh-cn/dotnet/api/system.net.http.ihttpclientfactory?view=dotnet-plat-ext-3.1