后端实现大文件分片上传

news2024/10/6 10:29:23

项目框架 net6 webapi

放开上传大小限制

放开代码 | 框架层限制

在 Program.cs 文件中添加如下代码
不然会出现下面的限制错误

From表单限制:Failed to read the request form. Multipart body length limit 134217728 exceeded
请求体超长:Request body too large. The max request body size is 30000000 bytes.

builder.Services
    .Configure<KestrelServerOptions>(x =>
    {
        x.AllowSynchronousIO = true; // 配置可以同步请求读取流数据
        x.Limits.MaxRequestBodySize = int.MaxValue;
    })
    .Configure<IISServerOptions>(x =>
    {
        x.AllowSynchronousIO = true;
        x.MaxRequestBodySize = int.MaxValue; // 设置请求体可接收的最大值
    })
    .Configure<FormOptions>(x =>
    {
        // 设置表单上传文件的大小限制
        // 如果不配置,默认是128兆
        x.MultipartBodyLengthLimit = int.MaxValue;
    });

设置 nginx 或 iis 中的大小限制

IIS 层

找到对应程序的 web.config
添加如下代码配置:

<security>
  	  <requestFiltering>
    	    <!-- 1000 MB in bytes -->
    	    <requestLimits maxAllowedContentLength="1048576000" />
  	  </requestFiltering>
	</security>

若缺少 system.webServer 等节点,添加上即可
image.png

nginx 层

在 conf 文件里的 nginx.conf 配置文件 http 中添加节点

client_max_body_size 1000m;

image.png

分片上传代码实现

请求参数 UploadFileInChunksVO 类

/// <summary>
/// 功 能: N/A
/// V0.01 2023/10/24 17:56:36 xliu  初版
/// </summary>
public class UploadFileInChunksVO
{        
		/// <summary>
    ///  分片后的文件
    /// </summary>
    public IFormFile File { get; set; }
    /// <summary>
    /// 当前块,从1开始
    /// </summary>
    public int ChunkNumber { get; set; }

    /// <summary>
    /// 总块数
    /// </summary>
    public int TotalChunks { get; set; }
}

添加控制器 Controller

必须添加 [FromForm] 标识,不然 FIle 识别不到

AppSettings 是一个自行实现读取配置文件的方法
RunInterceptException 是自定义的异常类,统一错误捕获处会对这个做 400 的异常处理

public async Task<IActionResult> UploadFile([FromForm] UploadFileInChunksVO chunksVO)
{
    if (chunksVO.ChunkNumber == 0 || chunksVO.TotalChunks == 0)
        throw new RunInterceptException("上传的数据块标识能为0");

    // 创建用于存储上传文件的文件夹
    // 可以是读取当前服务的地址,我这边项目是集群化的所有存储地址必须是一个地方不然没办法合并
    var path = AppSettings.app(new string[] { "Startup", "AppData" }); 
    if (path == null || path.IsNullOrEmpty())
        throw new RunInterceptException("文件存储服务路径为空");

    var folderPath = Path.Combine(path, "Uploads", "JD_EDI");
    var tempPath = Path.Combine(folderPath, "Temp");

    await _fileService.UploadFileInChunksAsync(chunksVO.File, tempPath, chunksVO.ChunkNumber);

    // 上传最后一块了 进行合并
    if (chunksVO.ChunkNumber == chunksVO.TotalChunks)
    {
        // 构造合并后的文件路径
        var mergedFilePath = Path.Combine(folderPath, chunksVO.File.FileName);
        await _fileService.MergeFileAsync(mergedFilePath, tempPath, chunksVO.File.FileName, chunksVO.TotalChunks);
        // 合并后的操作
        var res = await _ediService.SalesStockAsync(mergedFilePath);
        return Ok("处理成功数:" + res);
    }

    return Ok("接收成功");
}

服务接口定义 IUploadFileService

项目做了接口、服务分离。使用依赖注入的方式
若没这项要求的 可以直接使用后面的方法实现

/// <summary>
/// 功 能: 上传文件服务
/// V0.01 2023/10/24 15:01:01 xliu  初版
/// </summary>
public interface IUploadFileService
{
    /// <summary>
    /// 分片上传文件
    /// </summary>
    /// <param name="file">正在上传的文件</param>
    /// <param name="tempFilePath">临时存储分片数据的目录</param>
    /// <param name="chunkNumber">当前分片块</param>
    /// <returns>最终文件保存路径</returns>
    Task<string> UploadFileInChunksAsync(IFormFile file, string tempFilePath , int chunkNumber);

    /// <summary>
    /// 用于合并文件块并处理完整文件的方法
    /// </summary>
    /// <param name="mergedFilePath">合并后文件的保存地址</param>
    /// <param name="tempPath">分片文件的保存地址</param>
    /// <param name="fileName"></param>
    /// <param name="totalChunks"></param>
    /// <returns></returns>
    Task MergeFileAsync(string mergedFilePath, string tempPath, string fileName, int totalChunks);
}

服务接口实现 UploadFileService

/// <summary>
/// 功 能: N/A
/// V0.01 2023/10/24 15:05:09 xliu  初版
/// </summary>
public class UploadFileService : IUploadFileService
{
    
    public async Task<string> UploadFileInChunksAsync(IFormFile file, string tempPath, int chunkNumber)
    {
        if (!Directory.Exists(tempPath))
        {
            Directory.CreateDirectory(tempPath);
        }

        // 构造当前块文件的路径
        var filePath = Path.Combine(tempPath, file.FileName + "_" + chunkNumber);
        // 将文件块写入磁盘
        using (var fileStream = new FileStream(filePath, FileMode.Create))
        {
            await file.CopyToAsync(fileStream);
        }
        
        return filePath;
    }

    public async Task MergeFileAsync(string mergedFilePath, string tempPath, string fileName, int totalChunks)
    {
        // 创建用于存储合并后文件的流
        using var mergedFileStream = new FileStream(mergedFilePath, FileMode.Create);
        // 循环处理每个文件块
        for (int i = 1; i <= totalChunks; i++)
        {
            // 构造当前文件块的路径
            var chunkFilePath = Path.Combine(tempPath, fileName + "_" + i);
            // 创建用于读取文件块的流
            using (var chunkFileStream = new FileStream(chunkFilePath, FileMode.Open))
            {
                // 将文件块内容复制到合并文件流中
                await chunkFileStream.CopyToAsync(mergedFileStream);
            }
            // 删除已合并的文件块
            System.IO.File.Delete(chunkFilePath);
        }
    }

上传测试

这边只给到 postman 的示例
前端实现 无非就是根据文件大小切分成多个文件 单次上传一部分
每次上传变化 file 和 chuckNumber 即可,当 chunkNumber 和 totalChunks 相等时便上传完成
image.png

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1136647.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

深入探究ASEMI肖特基二极管MBR60100PT的材质

编辑-Z 在电子零件领域中&#xff0c;肖特基二极管MBR60100PT因其出色的性能和广泛的应用而显得尤为关键。理解其材质不仅有助于我们深入理解其运作原理&#xff0c;也有助于我们做出更合适的电子设计。那么&#xff0c;肖特基二极管MBR60100PT是什么材质呢? 首先&#xff0c…

java版直播商城平台规划及常见的营销模式有哪些?电商源码/小程序/三级分销/手机商城免费搭建

涉及平台 平台管理、商家端&#xff08;PC端、手机端&#xff09;、买家平台&#xff08;H5/公众号、小程序、APP端&#xff08;IOS/Android&#xff09;、微服务平台&#xff08;业务服务&#xff09; 2. 核心架构 Spring Cloud、Spring Boot、Mybatis、Redis …

Visual C++编程初学者疑难问题大集合(一)

初学者在学习visual c时问题很多&#xff0c;有意思的是&#xff0c;很多问题教材上都不说&#xff0c;后台有不少小伙伴问我相关问题&#xff0c;我于是总结一下。以供学习visual c的小伙伴少走弯路。 问题一&#xff1a;怎么样快速运行一个程序&#xff1f; 鼠标双击Visual…

我的课程居然上热门了

记录一下&#xff0c;我的课程上热门了&#xff0c;排名第三&#xff0c;非常的开心

了解WebGL三维技术

文章目录 什么是WebGLWebGLOpenGL 什么是WebGL WebGL WebGL是一项结合了HTML5和JavaScript&#xff0c;用来在网页上绘制和渲染复杂三维图形的技术。WebGL通过JavaScript操作OpenGL接口的标准&#xff0c;把三维空间图像显示在二维的屏幕上。所以它的本质就是JavaScript操作O…

Leetcode—2520.统计能整除数字的位数【简单】

2023每日刷题&#xff08;十&#xff09; Leetcode—2520.统计能整除数字的位数 实现代码 int countDigits(int num){int ans 0;int val 0;int tmp num;while(tmp) {val tmp % 10;if(num % val 0) {ans;}tmp / 10;}return ans; } 运行结果 之后我会持续更新&#xff0c;…

安装虚拟机找不到虚拟网啦1(eth1)不出现

一、安装虚拟机找不到虚拟网啦1&#xff08;eth1&#xff09;不出现 1、先安装virtualbox 2、再安装vagrant 3、在windows使用ipconfig没有VirtualBoxHost-OnlyNetWork解决方法 1) 解决办法 在windows的设置中找到 网络和Internet 选项&#xff0c;选择右侧 更改适配器选项 …

「滚雪球学Java」:方法函数(章节汇总)

&#x1f3c6;本文收录于「滚雪球学Java」专栏&#xff0c;专业攻坚指数级提升&#xff0c;助你一臂之力&#xff0c;带你早日登顶&#x1f680;&#xff0c;欢迎大家关注&&收藏&#xff01;持续更新中&#xff0c;up&#xff01;up&#xff01;up&#xff01;&#xf…

批量手机号码归属地查询工具

在日常工作生活中&#xff0c;手机号码归属地的查询需求越来越普遍。 这款查询软件&#xff0c;具有高效、便捷、隐私保护等诸多优势&#xff0c;让您轻松解决手机号码归属地查询问题。 可以快速批量查询手机号码归属地&#xff0c;为您节省宝贵的时间和精力。 无需联网即可…

IP地址规划的基本方法

IP地址规划是构建和管理网络的关键步骤&#xff0c;它涉及到为网络中的设备分配合适的IP地址&#xff0c;以确保网络的高效性、安全性和可管理性。在本文中&#xff0c;我们将探讨IP地址规划的基本方法&#xff0c;以帮助网络管理员和工程师更好地设计和维护网络。 1. 理解IP地…

提升技能,一触即达!全新在线题库微信小程序等你来挑战!

亲爱的同学们&#xff0c;你是否在准备各种专业认证考试时&#xff0c;感到题目繁多&#xff0c;复习困难&#xff1f;你是否在寻找一个能够提供全方位、各级别认证考试题库的在线学习平台&#xff1f; 今天&#xff0c;我们为你带来了一款全新的在线题库微信小程序——KD蝌蚪阿…

myTracks for Mac:GPS轨迹记录器的强大与便捷

你是否曾经在户外活动或旅行中&#xff0c;希望能够记录下你的移动轨迹&#xff1f;或者在工作中&#xff0c;需要跟踪你的行程路线&#xff1f;myTracks for Mac 是一款强大的 GPS 轨迹记录器&#xff0c;它可以帮助你实现这些愿望。 myTracks 是一款专门为 Mac 设计的 GPS 轨…

homeassistant安装HACS应用商店

环境&#xff1a;iStoreOS&#xff0c;已在商店中安装homeassistant。 homeassistant在iStoreOS中是以docker容器运行的。 1、进入终端&#xff0c;输入账号和密码&#xff08;默认&#xff1a;root&#xff0c;password&#xff09; 查看容器&#xff1a;docker ps 进入容…

如何公网远程连接本地群晖NAS中的WebDAV

文章目录 1. 在群晖套件中心安装WebDav Server套件1.1 安装完成后&#xff0c;启动webdav服务&#xff0c;并勾选HTTP复选框 2. 局域网测试WebDav服务2.1 下载RaiDrive客户端2.2 打开RaiDrive&#xff0c;设置界面语言可以选择中文2.3 点击添加按钮&#xff0c;新建虚拟驱动区2…

4G通信电子标签

4G移动通信系统 4G最大的数据传输速率超过100Mbit/s&#xff0c;这个速率是移动电话数据传输速率的1万倍&#xff0c;也是3G移动电话速率的50倍。4G手机可以提供高性能的汇流媒体内容&#xff0c;并通过ID应用程序成为个人身份鉴定设备。它也可以接受高分辨率的电影和电视节目…

WebDAV之π-Disk派盘 + FX播放器

想要把手机、PC、NAS等设备上的视频在智能电视上大屏播放,支持超多格式的多合一视频播放器?快来试试FX播放器吧。 FX播放器除了存储在智能手机上的视频外,您网络上的视频也是实时无缝的,内置网络客户端支持各种协议,包括 FTP、HTTP 和 WebDAV。 支持弹出窗口,允许您在观…

Pytorch代码入门学习之分类任务(二):定义数据集

一、导包 import torch import torchvision import torchvision.transforms as transforms 二、下载数据集 2.1 代码展示 # 定义数据加载进来后的初始化操作&#xff1a; transform transforms.Compose([# 张量转换&#xff1a;transforms.ToTensor(),# 归一化操作&#x…

什么是 Node.js

目标 什么是 Node.js&#xff0c;有什么用&#xff0c;为何能独立执行 JS 代码&#xff0c;演示安装和执行 JS 文件内代码 讲解 Node.js 是一个独立的 JavaScript 运行环境&#xff0c;能独立执行 JS 代码&#xff0c;因为这个特点&#xff0c;它可以用来编写服务器后端的应用…

position:sticity简介

一句话描述position: sticky的作用&#xff1a;让sticky元素在不超出包含块(containing block)的前提下尽可能展示在最近滚动祖先元素(nearest scrollport)的视口内。 怎么判断最近滚动祖先元素&#xff1f; 祖先元素中有overflow属性值不是visible和clip的都是滚动元素&…

Uni-app智慧工地可视化信息平台源码

智慧工地的核心是数字化&#xff0c;它通过传感器、监控设备、智能终端等技术手段&#xff0c;实现对工地各个环节的实时数据采集和传输&#xff0c;如环境温度、湿度、噪音等数据信息&#xff0c;将数据汇集到云端进行处理和分析&#xff0c;生成各种报表、图表和预警信息&…