支持多个文件上传,支持附带Json数据。

后台接口:

[HttpPost]
[Route("UploadFile")]
public async Task<IActionResult> UploadFile()
{
var files = Request.Form.Files;
var data = JsonConvert.DeserializeObject<UploadFileEntity>(Request.Form["data"]);

string snPath = $"{_hostingEnvironment.WebRootPath}//{_config["UploadPath"]}//{data.sn}";
foreach (var item in data.files)
{
var processPath = $"{snPath}//{ ConversionPath(item.processPath)}";
if (!Directory.Exists(processPath))
{
Directory.CreateDirectory(processPath);
}
var file = files.Where(p => p.FileName == item.fileName).FirstOrDefault();

if (file!=null && file.Length != 0)
{
// 只保留三份有效文件
DirectoryInfo di = new DirectoryInfo(processPath);
FileInfo[] oldFiles = di.GetFiles($"*{file.FileName}");
string newFileName = $"{(oldFiles.Length + 1)}_{file.FileName}";
if (oldFiles.Length == 3)
{
newFileName = oldFiles.OrderBy(f => f.LastWriteTime).FirstOrDefault().Name;
}
var filePath = $"{processPath}//{newFileName}";
using (var stream = new FileStream(filePath, FileMode.Create))
{
await file.CopyToAsync(stream);
}
}
}
return NoContent();
}

private string ConversionPath(string processPath)
{
return Regex.Replace(processPath.Replace("\\","_"), "/|:|:|“|”|<|>| ", "_").ToLower().TrimEnd('_');
}

参数实体:

public class UploadFileEntity
{
public string sn { get; set; }
public List<File> files { get; set; }
}
public class File
{
public string processPath { get; set; }
public string fileName { get; set; }
}

测试例子,用Ajax上传:

<!DOCTYPE html>
<html lang="en">

<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
<script src="https://code.jquery.com/jquery-2.2.4.min.js"
integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44=" crossorigin="anonymous"></script>
</head>

<body>
<div>
<form id="uploadForm">
DC进程文件上传: <input type="file" name="file" multiple />
<input type="button" value="上传" onclick="doUpload()" />
</form>
</div>
</body>
<script>
function doUpload() {
var formData = new FormData($("#uploadForm")[0]);
const data = {
sn: "19F73025F392DDC2CAD7D436D50AB0DAAADF37932EF11BD846C4542798EEE8B0735A8D34E80AF96E866A3BC20F87871E",
files: [
{
processPath: "C:/abc/def/",
fileName: "新建文本文档 - 副本 (2).txt"
},
{
processPath: "D:/test/def",
fileName: "新建文本文档 - 副本 (3) - 副本.txt"
}
]
}
formData.append("data", JSON.stringify(data));
$.ajax({
url: 'http://192.168.1.231:8844/api/DCClient/UploadFile',
type: 'POST',
data: formData,
contentType: false,
processData: false,
success: function (returndata) {
alert(returndata);
},
error: function (returndata) {
alert(returndata);
}
});
}
</script>

</html>

控制台程序模拟上传:

using System;
using System.Collections.Generic;
using System.IO;
using System.Text;

namespace demo
{
/// <summary>
/// 表单数据项
/// </summary>
public class FormItemModel
{
/// <summary>
/// 表单键,request["key"]
/// </summary>
public string Key { set; get; }
/// <summary>
/// 表单值,上传文件时忽略,request["key"].value
/// </summary>
public string Value { set; get; }
/// <summary>
/// 是否是文件
/// </summary>
public bool IsFile
{
get
{
if (FileContent == null || FileContent.Length == 0)
return false;

if (FileContent != null && FileContent.Length > 0 && string.IsNullOrWhiteSpace(FileName))
throw new Exception("上传文件时 FileName 属性值不能为空");
return true;
}
}
/// <summary>
/// 上传的文件名
/// </summary>
public string FileName { set; get; }
/// <summary>
/// 上传的文件内容
/// </summary>
public Stream FileContent { set; get; }
}
}
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;

namespace demo
{
class Program
{
static void Main(string[] args)
{
var url = "http://127.0.0.1:5000/api/DCClient/UploadFile";
var log1 = @".\新建文本文档 - 副本 (2).txt";
var log2 = @".\新建文本文档 - 副本 (3) - 副本.txt";
var formDatas = new List<FormItemModel>();
//添加文件
formDatas.Add(new FormItemModel()
{
Key = "log1",
Value = "",
FileName = "新建文本文档 - 副本 (2).txt",
FileContent = File.OpenRead(log1)
});
formDatas.Add(new FormItemModel()
{
Key = "log2",
Value = "",
FileName = "新建文本文档 - 副本 (3) - 副本.txt",
FileContent = File.OpenRead(log2)
});
formDatas.Add(new FormItemModel()
{
Key = "data",
Value = "{'sn':'1BB6D070D1B3DAEE3483604CB2DE6646D142E44B3E0927B772AC5B55E614ACA6A554B4A38DF8BC32','files':[{'processPath':'E:\\DataConnect_V1.2.3 - 测试1\\DataConnect_V1.2.3\\Model\\','fileName':'DataMap.map'}]}"
});
//提交表单
var result = PostForm(url, formDatas);
Console.ReadKey();
}

/// <summary>
/// 使用Post方法获取字符串结果
/// </summary>
/// <param name="url"></param>
/// <param name="formItems">Post表单内容</param>
/// <param name="cookieContainer"></param>
/// <param name="timeOut">默认20秒</param>
/// <param name="encoding">响应内容的编码类型(默认utf-8)</param>
/// <returns></returns>
public static string PostForm(string url, List<FormItemModel> formItems, CookieContainer cookieContainer = null, string refererUrl = null, Encoding encoding = null, int timeOut = 20000 * 3)
{
HttpWebRequest request = (HttpWebRequest)WebRequest.Create(url);
#region 初始化请求对象
request.Method = "POST";
request.Timeout = timeOut;
request.Accept = "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8";
request.KeepAlive = true;
request.UserAgent = "Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36";
if (!string.IsNullOrEmpty(refererUrl))
request.Referer = refererUrl;
if (cookieContainer != null)
request.CookieContainer = cookieContainer;
#endregion

string boundary = "----" + DateTime.Now.Ticks.ToString("x");//分隔符
request.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
//请求流
var postStream = new MemoryStream();
#region 处理Form表单请求内容
//是否用Form上传文件
var formUploadFile = formItems != null && formItems.Count > 0;
if (formUploadFile)
{
//文件数据模板
string fileFormdataTemplate =
"\r\n--" + boundary +
"\r\nContent-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"" +
"\r\nContent-Type: application/octet-stream" +
"\r\n\r\n";
//文本数据模板
string dataFormdataTemplate =
"\r\n--" + boundary +
"\r\nContent-Disposition: form-data; name=\"{0}\"" +
"\r\n\r\n{1}";
foreach (var item in formItems)
{
string formdata = null;
if (item.IsFile)
{
//上传文件
formdata = string.Format(
fileFormdataTemplate,
item.Key, //表单键
item.FileName);
}
else
{
//上传文本
formdata = string.Format(
dataFormdataTemplate,
item.Key,
item.Value);
}

//统一处理
byte[] formdataBytes = null;
//第一行不需要换行
if (postStream.Length == 0)
formdataBytes = Encoding.UTF8.GetBytes(formdata.Substring(2, formdata.Length - 2));
else
formdataBytes = Encoding.UTF8.GetBytes(formdata);
postStream.Write(formdataBytes, 0, formdataBytes.Length);

//写入文件内容
if (item.FileContent != null && item.FileContent.Length > 0)
{
using (var stream = item.FileContent)
{
byte[] buffer = new byte[1024];
int bytesRead = 0;
while ((bytesRead = stream.Read(buffer, 0, buffer.Length)) != 0)
{
postStream.Write(buffer, 0, bytesRead);
}
}
}
}
//结尾
var footer = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
postStream.Write(footer, 0, footer.Length);
}
else
{
request.ContentType = "application/x-www-form-urlencoded";
}
#endregion

request.ContentLength = postStream.Length;

#region 输入二进制流
if (postStream != null)
{
postStream.Position = 0;
//直接写入流
Stream requestStream = request.GetRequestStream();

byte[] buffer = new byte[1024];
int bytesRead = 0;
while ((bytesRead = postStream.Read(buffer, 0, buffer.Length)) != 0)
{
requestStream.Write(buffer, 0, bytesRead);
}

debug
//postStream.Seek(0, SeekOrigin.Begin);
//StreamReader sr = new StreamReader(postStream);
//var postStr = sr.ReadToEnd();
postStream.Close();//关闭文件访问
}
#endregion

HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (cookieContainer != null)
{
response.Cookies = cookieContainer.GetCookies(response.ResponseUri);
}

using (Stream responseStream = response.GetResponseStream())
{
using (StreamReader myStreamReader = new StreamReader(responseStream, encoding ?? Encoding.UTF8))
{
string retString = myStreamReader.ReadToEnd();
return retString;
}
}
}
}
}