文件分片上传

ops/2024/11/26 10:42:15/

分片上传:

1、前端(vue2+elementui)

<template><div><el-upload:http-request="handleUpload":before-upload="beforeUpload"multiple:auto-upload="false":on-change="handleFileChange"><el-button slot="trigger" type="primary">选择文件</el-button><el-button type="success" @click="submitUpload" :disabled="!file">上传</el-button></el-upload><el-progress v-if="progress > 0" :percentage="progress" status="success"></el-progress></div>
</template><script>
export default {data() {return {file: null, // 当前文件progress: 0, // 上传进度chunkSize: 5 * 1024 * 1024, // 每个分片大小 5MB};},methods: {// 文件选择回调handleFileChange(file) {this.file = file.raw;},// 上传前检查beforeUpload(file) {if (file.type !== "application/pdf") {this.$message.error("只能上传 PDF 文件!");return false;}if (file.size > 50 * 1024 * 1024) {this.$message.error("文件大小不能超过 50MB!");return false;}return true;},// 分片上传逻辑async handleUpload(option) {const file = option.file;const totalChunks = Math.ceil(file.size / this.chunkSize);let uploadedChunks = 0;for (let i = 0; i < totalChunks; i++) {const start = i * this.chunkSize;const end = Math.min(file.size, start + this.chunkSize);const chunk = file.slice(start, end);const formData = new FormData();formData.append("chunk", chunk);formData.append("fileName", file.name);formData.append("chunkIndex", i);formData.append("totalChunks", totalChunks);try {await this.$axios.post("/api/upload/chunk", formData);uploadedChunks++;this.progress = Math.round((uploadedChunks / totalChunks) * 100);} catch (error) {this.$message.error("上传失败,请重试!");console.error(error);return;}}// 通知服务器合并文件try {await this.$axios.post("/api/upload/merge", { fileName: file.name, totalChunks });this.$message.success("文件上传成功!");} catch (error) {this.$message.error("文件合并失败!");console.error(error);}},submitUpload() {if (this.file) {this.handleUpload({ file: this.file });} else {this.$message.error("请选择文件!");}},},
};
</script>

后端(.net6 webApi)

  1. 分片上传接口
    用于保存文件分片到临时目录:
[HttpPost("chunk")]
public async Task<IActionResult> UploadChunk([FromForm] IFormFile chunk, [FromForm] string fileName, [FromForm] int chunkIndex, [FromForm] int totalChunks)
{try{var tempFolder = Path.Combine("TempChunks", fileName);if (!Directory.Exists(tempFolder))Directory.CreateDirectory(tempFolder);var chunkPath = Path.Combine(tempFolder, $"{chunkIndex}");using (var stream = new FileStream(chunkPath, FileMode.Create)){await chunk.CopyToAsync(stream);}return Ok(new { success = true });}catch (Exception ex){return BadRequest(new { success = false, message = ex.Message });}
}
  1. 文件合并接口
    用于将所有分片合并为一个完整文件:
[HttpPost("merge")]
public async Task<IActionResult> MergeFile([FromBody] MergeRequest mergeRequest)
{try{var tempFolder = Path.Combine("TempChunks", mergeRequest.FileName);if (!Directory.Exists(tempFolder))return BadRequest(new { success = false, message = "分片目录不存在" });var finalFolder = Path.Combine("Uploads");if (!Directory.Exists(finalFolder))Directory.CreateDirectory(finalFolder);var finalFilePath = Path.Combine(finalFolder, mergeRequest.FileName);using (var finalFileStream = new FileStream(finalFilePath, FileMode.Create)){for (int i = 0; i < mergeRequest.TotalChunks; i++){var chunkPath = Path.Combine(tempFolder, $"{i}");if (!System.IO.File.Exists(chunkPath))return BadRequest(new { success = false, message = $"缺少分片 {i}" });var chunkData = await System.IO.File.ReadAllBytesAsync(chunkPath);await finalFileStream.WriteAsync(chunkData, 0, chunkData.Length);System.IO.File.Delete(chunkPath); // 删除已合并的分片}}Directory.Delete(tempFolder); // 删除临时目录return Ok(new { success = true, path = $"/Uploads/{mergeRequest.FileName}" });}catch (Exception ex){return BadRequest(new { success = false, message = ex.Message });}
}public class MergeRequest
{public string FileName { get; set; }public int TotalChunks { get; set; }
}


http://www.ppmy.cn/ops/136812.html

相关文章

react项目初始化配置步骤

1.npx create-react-app 项目名称 vue项目同理 2.去编辑器市场安装所需插件&#xff0c;例如ESlint以及Prettier-Code formatter formatiing-toggle 3.在项目中安装 ESLint 和 Prettier 及相关插件&#xff1a; 3.1&#xff1a; npm install --save-dev eslint prettier 3.2…

非递归遍历二叉树(数据结构)

我的博客主页 非递归遍历二叉树 前序遍历&#xff08;迭代&#xff09;中序遍历&#xff08;迭代&#xff09;后续遍历&#xff08;迭代&#xff09; 二叉树的遍历方式有&#xff1a;前序遍历、中序遍历、后续遍历&#xff0c;层序遍历&#xff0c;而树的大部分情况下都是通过递…

使用 Python 的 pdfplumber 库高效解析 PDF 文件

使用 Python 的 pdfplumber 库高效解析 PDF 文件 PDF 文件是日常办公和数据处理中常见的文件格式&#xff0c;而 pdfplumber 是一个专为 PDF 文件解析设计的 Python 库&#xff0c;可以轻松提取文本、表格、图像等内容。本文将介绍 pdfplumber 的基本功能、使用方法&#xff0…

计算机网络谢希仁第七章课后题【背诵版本】

目录 【7-01】计算机网络都面临哪几种威胁?主动攻击和被动攻击的区别是什么?对于计算机网络的安全措施都有哪些? 【7-02】 试解释以下名词:(2)拒绝服务;(3)访问控制;(4)流量分析;(5)恶意程序。 【7-03】为什么说&#xff0c;计算机网络的安全不仅仅局限于保密性?试举例说…

openssl创建自签名证书

原文地址&#xff1a;自签名证书 – 无敌牛 欢迎参观我的个人博客&#xff1a;无敌牛 – 技术/著作/典籍/分享等 1 生成私钥 openssl genrsa -out server.key 2048 2 创建证书请求文件 openssl req -new -key server.key -out server.csr 3 用私钥和证书请求文件&#xf…

opencv读写文件操作

读取图像文件 OpenCV 中使用cv2.imread()函数来读取图像文件。这个函数的第一个参数是图像文件的路径&#xff0c;第二个参数是一个可选的标志&#xff0c;用于指定读取图像的方式。示例代码&#xff1a; import cv2 # 以彩色模式读取图像&#xff08;这是默认模式&#xff09…

HTML实现 扫雷游戏

前言&#xff1a; 游戏起源与发展 扫雷游戏的雏形可追溯到 1973 年的 “方块&#xff08;cube&#xff09;” 游戏&#xff0c;后经改编出现了 “rlogic” 游戏&#xff0c;玩家需为指挥中心探出安全路线避开地雷。在此基础上&#xff0c;开发者汤姆・安德森编写出了扫雷游戏的…

Python学习——猜拳小游戏

import random player int(input(“请输入&#xff1a;剪刀 0&#xff0c;石头 1&#xff0c;布2”)) computer random.randint(0,2)# print(“玩家输入的是%d&#xff0c;电脑输入的是%d” %(player,computer)) 用于测试 if (player 0) and (computer 0) or (player 1) a…