.NET MVC项目中,C#怎样实现文件夹的断点续传上传(含示例)?
·
大文件上传系统开发吐槽日记
甲方爸爸的需求清单
作为一个浙江苦逼的.NET程序员,最近接了个外包项目,甲方爸爸的需求让我差点当场表演"程序员暴毙":
- 文件传输:要传20G的文件,还得是文件夹(可能包含1000+文件)
- 加密要求:传输要SM4/AES加密,存储也要加密
- 断点续传:关浏览器、重启电脑都不能丢进度
- 兼容性:从IE8到现代浏览器全都要支持
- 预算:100块(我寻思这连服务器一天的电费都不够)
- 服务:7*24小时免费技术支持+源码+部署一条龙
技术选型困境
前端方案
// 看到IE8兼容要求时的我
function handleIe8Compatibility() {
if (isIE8()) {
console.log("建议用户升级浏览器");
throw new Error("老板说必须兼容,代码还得写");
}
}
后端存储方案
// 看到20G文件存储时的数据库设计
public class FileStorage
{
// 甲方:就用SQL Server存文件
public void Store20GBFile()
{
// 我的内心:E盘会不会爆炸?
var freeSpace = DriveInfo.GetDrives()
.First(d => d.Name == "E").TotalFreeSpace;
if (freeSpace < 20L * 1024 * 1024 * 1024)
{
throw new OutOfDiskSpaceException("甲方爸爸,加个硬盘呗?");
}
}
}
部分实现代码
前端文件上传核心逻辑
// 基于WebUploader的魔改版,兼容IE8
(function() {
// IE8 polyfill大礼包
if (!Array.prototype.forEach) {
Array.prototype.forEach = function(callback) {
for (var i = 0; i < this.length; i++) {
callback(this[i], i, this);
}
};
}
// 文件夹上传逻辑
function uploadFolder(folder) {
// 遍历文件夹结构
traverseFolder(folder, function(file) {
// 保持相对路径
var relativePath = getRelativePath(file);
// 分片上传
uploadFileInChunks(file, relativePath);
});
}
// 断点续传实现
function resumeUpload(fileId) {
checkServerForProgress(fileId, function(progress) {
if (progress < 100) {
console.log("从" + progress + "%继续上传");
// 继续上传逻辑
}
});
}
})();
后端C#处理代码
// 文件上传处理
public class FileUploadHandler : IHttpHandler
{
public void ProcessRequest(HttpContext context)
{
try
{
// 获取上传文件
HttpPostedFile file = context.Request.Files[0];
string relativePath = context.Request["relativePath"];
// 加密存储
using (var cryptoStream = new CryptoStream(
File.Create(Path.Combine("E:\\Uploads", relativePath)),
new SM4CryptoProvider().CreateEncryptor(),
CryptoStreamMode.Write))
{
file.InputStream.CopyTo(cryptoStream);
}
// 记录上传进度到数据库
RecordUploadProgress(context.Request["fileId"], 100);
}
catch (Exception ex)
{
// 100块预算的异常处理
context.Response.Write("出错啦!但我们没钱修!");
}
}
private void RecordUploadProgress(string fileId, int progress)
{
// SQL Server操作
using (var conn = new SqlConnection("连不起Azure只能用本地..."))
{
conn.Open();
// 省略一万行SQL...
}
}
}
开发者的自我修养
-
兼容IE8的绝招:
- 准备大量polyfill
- 放弃使用任何现代CSS特性
- 把jQuery 1.x刻进DNA
- 每晚祈祷用户早日升级
-
大文件上传秘籍:
// 分片上传伪代码 while(budget < projectCost) { Console.WriteLine("再接个外包补这个窟窿"); budget += 100; // 每个项目都预算100 } -
加密存储小技巧:
// 前端加密演示 function encrypt(data) { if (budget > 0) { return realEncrypt(data); // 真加密 } else { return data; // 预算不足时的"加密" } }
项目总结
这个项目教会了我:
- 如何用100块预算做出10万块的功能
- 如何在2023年继续伺候IE8这位"老佛爷"
- 如何在不睡觉的情况下提供7*24支持
- 为什么程序员会秃头
最终方案:建议甲方加钱,或者我把QQ群(374992201)里的"大神"们介绍给他,毕竟:
- 加群送红包
- 推荐有提成
- “超级会员直接50%提成”
- 大家一起用爱发电
(免责声明:以上代码仅供娱乐,实际开发请根据预算调整功能范围)
设置框架
安装.NET Framework 4.7.2
https://dotnet.microsoft.com/en-us/download/dotnet-framework/net472
框架选择4.7.2

添加3rd引用

编译项目

NOSQL
NOSQL无需任何配置可直接访问页面进行测试

SQL
使用IIS
大文件上传测试推荐使用IIS以获取更高性能。

使用IIS Express
小文件上传测试可以使用IIS Express

创建数据库

配置数据库连接信息

检查数据库配置

访问页面进行测试

相关参考:
文件保存位置,
效果预览
文件上传

文件刷新续传
支持离线保存文件进度,在关闭浏览器,刷新浏览器后进行不丢失,仍然能够继续上传

文件夹上传
支持上传文件夹并保留层级结构,同样支持进度信息离线保存,刷新页面,关闭页面,重启系统不丢失上传进度。

下载示例
更多推荐
所有评论(0)