C# .NET WebForm如何实现大文件续传效果代码示例?

开发日记:大文件上传系统攻坚记
日期:2023年XX月XX日
天气:晴(但心情像在调试IE8的阴天)


一、需求拆解:从"不可能"到"可能"

客户的需求像一座高山:

  • 20G文件传输(阿里云OSS单文件上限5TB,但浏览器内存是瓶颈)
  • IE8兼容(默默掏出XDomainRequestActiveXObject的祖传代码)
  • 文件夹层级保留(需递归处理``的FileSystemEntry API)
  • 断点续传+加密(分片上传+本地存储恢复点+Web Crypto API)

技术选型

  • 放弃WebUploader(IE8支持不足),选择原生JS+H5 File API
  • 加密方案:SM4/AES通过forge.js兼容旧浏览器
  • 断点续传:localStorage+服务端分片记录

二、前端核心代码:文件夹上传与断点续传

1. 文件夹上传(递归扫描)
// 获取文件夹所有文件(兼容IE10+,IE8需ActiveX降级方案)
async function scanDirectory(directory) {
const files = [];
const stack = [directory];
while (stack.length) {
const entry = stack.pop();
if (entry.isFile) {
files.push(await getFile(entry));
} else if (entry.isDirectory) {
const reader = entry.createReader();
const entries = await new Promise(resolve => reader.readEntries(resolve));
stack.push(...entries);
}
}
return files;
}
// IE8降级方案(需用户手动选择多个文件)
function handleIE8Fallback() {
const input = document.createElement('input');
input.type = 'file';
input.multiple = true;
input.onchange = () =>
uploadFiles(input.files);
input.click();
}
2. 分片上传+断点续传
class ChunkUploader
{
constructor(file, options) {
this.file = file;
this.chunkSize = 5 * 1024 * 1024;
// 5MB/chunk
this.totalChunks = Math.ceil(file.size / this.chunkSize);
this.uploadedChunks = JSON.parse(localStorage.getItem(file.name) || '[]');
}
async upload() {
for (let i = 0; i <
this.totalChunks; i++) {
if (this.uploadedChunks.includes(i)) continue;
const chunk = this.file.slice(i * this.chunkSize, (i + 1) * this.chunkSize);
await this.sendChunk(chunk, i);
this.uploadedChunks.push(i);
localStorage.setItem(this.file.name, JSON.stringify(this.uploadedChunks));
}
}
async sendChunk(chunk, index) {
const formData = new FormData();
formData.append('chunk', chunk);
formData.append('chunkIndex', index);
formData.append('totalChunks', this.totalChunks);
formData.append('fileId', btoa(this.file.name + this.file.size));
// 唯一标识
return fetch('/api/upload', { method: 'POST', body: formData
});
}
}

三、后端C#代码:分片处理与加密存储

1. 分片接收(ASP.NET WebForm)
[WebMethod]
public static string UploadChunk()
{
HttpPostedFile chunk = HttpContext.Current.Request.Files["chunk"];
int index = int.Parse(HttpContext.Current.Request["chunkIndex"]);
string fileId = HttpContext.Current.Request["fileId"];
// 存储分片到临时目录
string tempPath = Path.Combine(Server.MapPath("~/App_Data/Temp"), fileId);
Directory.CreateDirectory(tempPath);
chunk.SaveAs(Path.Combine(tempPath, index.ToString()));
// 检查是否完成
if (AllChunksReceived(tempPath, int.Parse(HttpContext.Current.Request["totalChunks"])))
{
MergeFile(tempPath, fileId);
}
return "OK";
}
2. SM4加密存储(使用BouncyCastle库)
public static void EncryptToOSS(Stream input, string ossKey)
{
var engine = new SM4Engine();
var key = Encoding.UTF8.GetBytes("16-byte-secret-key");
engine.Init(true, new KeyParameter(key));
using (var ossClient = new OssClient(endpoint, accessKeyId, accessKeySecret))
using (var cryptoStream = new CryptoStream(input, engine, CryptoStreamMode.Read))
{
ossClient.PutObject(bucketName, ossKey, cryptoStream);
}
}

四、踩坑实录

  1. IE8的棺材板快压不住了
    • 解决方案:对文件夹上传降级为多文件选择,用swfUpload后备方案
  2. 20G文件内存溢出
    • 优化:采用FileReaderreadAsArrayBuffer分段处理
  3. 文件夹层级丢失
    • 关键:上传时携带相对路径,如/科研资料/2023/实验报告.pdf

五、部署与协作

  • 阿里云OSS配置:开启断点续传和跨域规则
  • SQL Server设计
    CREATE TABLE FileTransfers (
    FileId VARCHAR(255) PRIMARY KEY,
    OriginalName NVARCHAR(255),
    OSSPath VARCHAR(255),
    ChunkCount INT,
    CompletedChunks VARCHAR(MAX) -- JSON格式存储已上传分片
    )
  • 接单群协作:代码已上传至群文件(QQ群:374992201),含完整文档

明日计划

  • 测试CentOS下Mono运行ASP.NET的兼容性
  • 编写IE8的ActiveX加密模块(仿佛回到2010年)

签名
—— 一个在古董浏览器和现代需求间挣扎的开发者

设置框架

安装.NET Framework 4.7.2
https://dotnet.microsoft.com/en-us/download/dotnet-framework/net472
框架选择4.7.2
Alt

添加3rd引用

Alt

编译项目

Alt

NOSQL

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

SQL

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

使用IIS Express

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

创建数据库

Alt

配置数据库连接信息

Alt

检查数据库配置

Alt

访问页面进行测试

Alt
相关参考:
文件保存位置

效果预览

文件上传

文件上传

文件刷新续传

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

文件夹上传

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

批量下载

支持文件批量下载
批量下载

下载续传

文件下载支持离线保存进度信息,刷新页面,关闭页面,重启系统均不会丢失进度信息。
下载续传

文件夹下载

支持下载文件夹,并保留层级结构,不打包,不占用服务器资源。
文件夹下载

下载示例

下载完整示例

posted on 2025-10-10 15:57  slgkaifa  阅读(10)  评论(0)    收藏  举报

导航