研究了几天的 WebAPI 多文件批量上传功能,也终于找到了无法先验证再存盘的解决方法,以下是本次的测试代码,希望能对大家有帮助!~
-
首先上服务端多文件接收的接口代码
public class FileController : ServiceBase
{
///
/// 服务端文件上传接口
///
[Route("~/upload")]
[HttpPost, HttpGet]
public async Task<string> Upload()
{
System.Diagnostics.Debugger.Launch(); //唤起调试器
if (!Request.Content.IsMimeMultipartContent())
return "缺少附件。";
var savePath = $@"D:\ReceiveUpload\{DateTime.Now.ToString("yyyy-MM-dd")}"; //定义一个用于存储接收文件的目录
//确保目录存在
if (!Directory.Exists(savePath))
Directory.CreateDirectory(savePath);
//使用异步接收客户端上传的多个文件信息
var multi = await Request.Content.ReadAsMultipartAsync();
var fileCount = 0;
//遍历全部文件
foreach (var content in multi.Contents)
{
var contentType = content.Headers.ContentType; //客户端定义的Content-Type
var name = content.Headers.ContentDisposition.Name; //客户端定义的Name参数
var fileName = content.Headers.ContentDisposition.FileName?.Trim('"'); //客户端上传的文件名称
var fileType = Path.GetExtension(fileName)?.TrimStart('.'); //获取文件扩展名
if (string.IsNullOrWhiteSpace(fileName))
continue;//非文件则跳过
++fileCount;
//获取文件流数据(根据自己需求2选1即可)
var fileBytes = await content.ReadAsByteArrayAsync();
var fileStream = await content.ReadAsStreamAsync();
var fileLength = fileStream.Length; //获取文件大小
switch (fileType.ToLower())
{
case "jpg":
case "png":
#region 验证图片文件
{
var image = new Bitmap(fileStream); //获取图片信息
var imgWidth = image.Width; //获取图片宽度
var imgHeight = image.Height; //获取图片高度
var imgLength = fileStream.Length; //获取图片大小
//PS:可在此处对图片大小与分辨率大小进行验证
//将此图片保存到磁盘
image.Save($@"{savePath}\{fileName}");
//释放资源
image.Dispose();
}
#endregion
break;
default:
//return $"不允许的文件格式“{fileType}”。";
//将文件保存到磁盘中
File.WriteAllBytes($@"{savePath}\{fileName}", fileBytes);
break;
}
//释放资源
fileStream.Dispose();
}
return $"已接收到{fileCount}个文件。";
}
}
-
其次是客户端程序的文件上传代码
/// <summary>
/// 客户端批量上传文件
/// </summary>
[TestMethod]
public void TestUpload()
{
var url = "http://127.0.0.1:8080/upload";
var filesPath = new List<string>();
{
filesPath.Add(@"D:\测试文件\17,443KB (9088x3776).jpg");
filesPath.Add(@"D:\测试文件\829KB.7z");
filesPath.Add(@"D:\测试文件\107MB.zip");
filesPath.Add(@"D:\测试文件\812MB.rar");
}
using (var client = new System.Net.Http.HttpClient())
using (var content = new System.Net.Http.MultipartFormDataContent())
{
foreach (string filePath in filesPath)
#region 添加文件
{
var fileName = filePath.Substring(filePath.LastIndexOf('\\') + 1);
var fileBytes = File.ReadAllBytes(filePath);
var fileContent = new System.Net.Http.ByteArrayContent(fileBytes);
{
//定义内容标头,使用 attachment 附件上传模式
fileContent.Headers.ContentDisposition = new System.Net.Http.Headers.ContentDispositionHeaderValue("attachment")
{
//定义一个Name参数 (非必填项,根据个人需求即可)
Name = $"文件{++i}",
//告诉服务端当前文件的名称
FileName = fileName
};
}
content.Add(fileContent);
}
#endregion
var responseMessage = client.PostAsync(url, content).Result;
var status = responseMessage.StatusCode;
var result = responseMessage.Content.ReadAsStringAsync().Result; //返回的页面内容
//测试结果返回:"已接收到4个文件。"
}
}
-
以上,如出现 Request 内容超过限制的长度异常,注意配置 Web.config
<!--修改限制Request数据大小(单位:KB)-->
<system.web>
<httpRuntime targetFramework="4.6.1" maxRequestLength="4194304"/>
</system.web>
<!--修改限制Request数据大小(单位:Byte)-->
<system.webServer>
<security>
<requestFiltering>
<requestLimits maxAllowedContentLength="4294967295" />
</requestFiltering>
</security>
</system.webServer>
-
若上一步配置后还没能解决的,可再尝试修改 App_Start/WebApiConfig.cs
此处是在 https://www.cnblogs.com/dopeter/p/4675174.html 这篇文章中看到的,因实际测试时已通过上一步的配置 Web.config 已解决,所以还没能用上这段 ~ :-)
public static class WebApiConfig
{
public static void Register(HttpConfiguration config)
{
// 重写上传文件的内容存入内存的动作,为解决无法通过流上传大文件问题
GlobalConfiguration.Configuration.Services.Replace(typeof(System.Web.Http.Hosting.IHostBufferPolicySelector), new NoBufferPolicySelector());
}
}
/// <summary>
/// 重写上传文件的内容存入内存的动作,为解决无法通过流上传大文件问题
/// </summary>
public class NoBufferPolicySelector : System.Web.Http.WebHost.WebHostBufferPolicySelector
{
public override bool UseBufferedInputStream(object hostContext)
{
var context = hostContext as System.Web.HttpContextBase;
if (context != null)
{
if (context.Request.HttpMethod == System.Net.Http.HttpMethod.Post.ToString() && context.Request.ContentLength > 200000)
return false;
}
return true;
}
}