政府项目大文件传输系统开发纪实

项目背景与核心诉求

作为山东某软件公司技术负责人,近期承接省级政府招投标平台升级项目,面临以下技术挑战:

  1. 超大文件支持:需稳定传输20G级招标文件(含图纸、视频等)
  2. 文件夹结构保留:要求完整保留三级文件夹层级关系
  3. 全平台兼容
    • 浏览器:Chrome/Firefox/龙芯浏览器(MIPS架构)
    • 操作系统:统信UOS V20/中标麒麟V7.0
  4. 国产化数据库适配:达梦8.x/人大金仓V8
  5. 技术可控性:需获取完整源代码进行定制开发

技术选型与架构设计

前端技术栈(ASP.NET WebForm)






    // 文件夹上传处理
    function handleFolder(files) {
        const folderData = {
            name: '招标文件',
            path: '/root',
            children: []
        };
        
        // 递归遍历文件结构
        const walker = files.webkitGetAsEntry();
        traverseFileTree(walker, folderData);
        
        // 序列化结构数据
        const structure = JSON.stringify(folderData);
        $.ajax({
            url: '/api/folder',
            method: 'POST',
            data: { structure: structure }
        });
    }
    
    // 分片上传实现
    function uploadChunk(file, start, end) {
        const chunk = file.slice(start, end);
        const formData = new FormData();
        formData.append('chunk', chunk);
        formData.append('index', currentIndex);
        formData.append('total', totalChunks);
        
        $.ajax({
            url: '/api/upload',
            method: 'POST',
            data: formData,
            processData: false,
            contentType: false,
            success: function(res) {
                updateProgress(res.progress);
            }
        });
    }

后端架构设计(ASP.NET Core)

// 分片上传接口
[HttpPost("/api/upload")]
public async Task UploadChunk(IFormFile chunk, int index, int total)
{
    var md5 = Request.Headers["X-File-MD5"].FirstOrDefault();
    var tempPath = Path.Combine("temp", $"{md5}-{index}");
    
    // 保存分片
    using (var stream = new FileStream(tempPath, FileMode.Create))
    {
        await chunk.CopyToAsync(stream);
    }
    
    // 更新数据库状态
    _dbContext.UploadTasks.Update(new UploadTask {
        FileMD5 = md5,
        FinishedChunks = index,
        TotalChunks = total,
        Status = index == total -1 ? "Merging" : "Uploading"
    });
    
    return Ok(new { progress = (index+1)*100/total });
}

// 合并文件接口
[HttpPost("/api/merge")]
public IActionResult MergeFile(string md5)
{
    var finalPath = Path.Combine("uploads", md5);
    var tempFiles = Directory.GetFiles("temp", $"{md5}-*");
    
    // 按索引排序合并
    Array.Sort(tempFiles, (x,y) => 
        int.Parse(Path.GetFileNameWithoutExtension(y).Split('-')[1]) -
        int.Parse(Path.GetFileNameWithoutExtension(x).Split('-')[1])
    );
    
    using (var fs = new FileStream(finalPath, FileMode.Create))
    {
        foreach (var tempFile in tempFiles)
        {
            var buffer = System.IO.File.ReadAllBytes(tempFile);
            fs.Write(buffer, 0, buffer.Length);
            System.IO.File.Delete(tempFile); // 清理临时文件
        }
    }
    
    // 记录数据库完成状态
    _dbContext.UploadTasks.Update(new UploadTask {
        Status = "Completed",
        FinishedAt = DateTime.UtcNow
    });
    
    return Ok(new { url = $"/uploads/{md5}" });
}

国产化适配关键技术

信创浏览器兼容方案

// 浏览器检测中间件
public class BrowserDetectionMiddleware
{
    private readonly RequestDelegate _next;
    
    public BrowserDetectionMiddleware(RequestDelegate next)
    {
        _next = next;
    }
    
    public async Task Invoke(HttpContext context)
    {
        var userAgent = context.Request.Headers["User-Agent"].ToString();
        
        if (userAgent.Contains("Red莲花")) {
            context.Items["BrowserType"] = "HongLianHua";
            // 特殊处理:关闭HTTP/2强制使用HTTP/1.1
            context.Features.Set(null);
        }
        else if (userAgent.Contains("Qianxin")) {
            context.Items["BrowserType"] = "Qianxin";
            // 调整上传分片大小至2MB
            context.Features.Get().MaxRequestBodySize = 2 * 1024 * 1024;
        }
        
        await _next(context);
    }
}

跨数据库适配层(达梦/人大金仓)

public class DbFactory
{
    public static IDbConnection CreateConnection(string dbType)
    {
        switch(dbType.ToLower())
        {
            case "dm":
                return new DmConnection(Configuration["ConnectionStrings:Dm"]);
            case "kingbase":
                return new KingbaseESConnection(Configuration["ConnectionStrings:Kingbase"]);
            default:
                return new SqlConnection(Configuration["ConnectionStrings:Default"]);
        }
    }
}

// 使用示例
using (var conn = DbFactory.CreateConnection("dm"))
{
    conn.Open();
    var cmd = conn.CreateCommand();
    cmd.CommandText = "INSERT INTO upload_tasks (...) VALUES (...)";
    cmd.ExecuteNonQuery();
}

测试验证矩阵

测试维度测试用例预期结果实际结果
文件大小20G单个文件上传3小时内完成
文件夹结构3级目录(含空文件夹)完整保留结构
浏览器兼容龙芯浏览器(MIPS架构)上传进度正常显示
数据库切换达梦8.x与SQL Server交替使用数据一致性验证通过
断点续传网络中断后继续上传正确续传不重复

部署与维护方案

服务器配置优化

# 统信UOS系统调优
echo "vm.max_map_count=262144" >> /etc/sysctl.conf
sysctl -p

# 配置临时存储空间
mkdir /data/temp_uploads
mount -t tmpfs -o size=40G tmpfs /data/temp_uploads

监控报警设置

// 自定义健康检查接口
[HttpGet("/health")]
public IActionResult HealthCheck()
{
    var tempSpace = new DriveInfo("/data").AvailableFreeSpace;
    if (tempSpace < 10 * 1024 * 1024 * 1024) // 低于10G报警
    {
        // 触发钉钉机器人告警
        SendDingTalkAlert($"临时存储空间不足: {tempSpace/1024/1024}MB");
    }
    
    return Ok(new { status = "healthy" });
}

技术交流与支持

为满足政府项目特殊需求,建立专项技术支撑体系:

  1. 源代码管理:GitLab私有仓库(访问地址:http://git.sdgov.com)
  2. 问题跟踪:Jira专项板(项目代码:GOV-UPLOAD-2025)
  3. 应急响应:7×24小时值班制度(联系电话:0531-XXXXXXX)

欢迎同行加入技术交流QQ群374992201,重点探讨:

  • 信创浏览器兼容性解决方案
  • 国产化数据库索引优化策略
  • 大文件传输安全加固方案

通过本次项目实践,成功构建了符合国家信创标准的大文件传输系统,为政府数字化转型提供了可靠的技术支撑。

设置框架

安装.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
相关参考:
文件保存位置

效果预览

文件上传

文件上传

文件刷新续传

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

文件夹上传

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

批量下载

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

下载续传

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

文件夹下载

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

下载完整示例

下载完整示例

Logo

Agent 垂直技术社区,欢迎活跃、内容共建。

更多推荐