首页 > 其他分享 >.Net +Ajax大文件断点续传

.Net +Ajax大文件断点续传

时间:2023-12-20 10:14:51浏览次数:35  
标签:断点续传 endByte 文件 xhr 传输 Ajax var Net 上传

什么是断点续传
大文件断点续传指的是在上传或下载大文件时,当传输中断或出现错误时,可以通过记录已经传输的数据和位置,下次从中断的位置继续传输,避免重新开始传输整个文件的过程,从而提高传输效率和稳定性。

实现思路
获取文件大小和已经传输的大小:在开始上传或下载文件之前,需要获取文件的总大小和已经传输的大小,以便于记录已经传输的数据和位置。

记录已经传输的数据和位置:在传输过程中,需要记录已经传输的数据和位置。通常可以将已经传输的数据写入到本地的缓存文件中,下次传输时从缓存文件中读取已经传输的数据和位置,然后从该位置继续传输。

实现断点续传:当传输中断或出现错误时,可以通过读取本地的缓存文件获取已经传输的数据和位置,然后从该位置继续传输,避免重新开始传输整个文件的过程。

检查传输完整性:在传输完成后,需要检查传输的完整性,以确保文件传输没有出现问题。通常可以通过比较传输的文件大小和本地文件的大小来检查传输的完整性

实际项目中需要考虑的细节和安全性问题
分块大小的选择:分块大小的选择应该考虑到上传速度和服务器处理能力,一般建议选择 1MB 到 4MB 的大小。

文件名的处理:在上传时应该对文件名进行编码,以避免文件名中包含非法字符导致的错误。

安全性:上传的文件可能包含恶意代码,因此需要对上传的文件进行校验和过滤,以确保上传的文件是安全的。可以对文件的扩展名、大小、MIME 类型等进行校验和过滤,或者使用一些成熟的第三方上传组件来提高安全性。

断点续传的处理:对于已经上传过的部分,需要对其进行检查和验证,以避免数据的重复和覆盖。可以在服务端保存已经上传的分块信息,以便于在续传时进行检查和验证。

并发上传的处理:并发上传可能会导致文件的不一致性,因此需要考虑并发上传时的锁机制,以保证上传的正确性和一致性。

上传进度的显示:在上传过程中,可以通过 Ajax 轮询或者 WebSocket 等技术实时显示上传进度,以提高用户体验。

文件上传的存储:在存储上传的文件时,应该将其存储在安全的位置,并且对文件的读写权限进行限制,以防止恶意访问和攻击。可以将文件存储在独立的服务器上,以提高安全性和可靠性。

上传速度的优化:上传大文件可能会消耗较长时间,可以通过使用分布式存储、CDN 加速等技术来优化上传速度和用户体验。

代码实现
<div>
<h1>大文件断点续传</h1>
<input type="file" id="fileUpload" />
<br /><br />
<button id="btnUpload">上传</button>
<br /><br />
<progress id="progressBar" value="0" max="100"></progress>
<br /><br />
<div id="status"></div>
<div><button id="stop">暂停/继续</button> </div>
</div>

<script type="text/javascript">
var file;
var chunkSize = 1024 * 1024; // 1MB
var startByte = 0;
var endByte = startByte + chunkSize;
var totalSize;
var loaded = 0;
var xhr;
var isStop = false;
$("#stop").click(function () {
if (file == null) return;
isStop = !isStop;
if (isStop == false) {

uploadChunk();
}
});

$("#fileUpload").change(function () {
file = this.files[0];
totalSize = file.size;
startByte = 0;
endByte = startByte + chunkSize;
});

$("#btnUpload").click(function () {
if (!file) {
alert("请选择文件.");
return;
}

xhr = new XMLHttpRequest();

xhr.upload.addEventListener("progress", function (e) {
loaded = startByte + e.loaded;
var percent = Math.floor((loaded / totalSize) * 100);
$("#progressBar").val(percent);
});

xhr.onreadystatechange = function () {
if (xhr.readyState === 4) {
if (xhr.status === 200) {
$("#status").text("上传成功!");
}
else if (xhr.status === 206) {
if (loaded < totalSize) {
startByte = endByte;
endByte = startByte + chunkSize;
if (isStop == false) {
uploadChunk();
}
} else {
$("#status").text("上传成功!");
}
} else {
//失败后继续重试上传
if (isStop == false) {
uploadChunk();
}
}
}
};

endByte = startByte + chunkSize;
uploadChunk();
});

function uploadChunk() {
if (endByte > totalSize) {
endByte = totalSize;
}
xhr.open("POST", "/File/Upload");
xhr.setRequestHeader("Content-Type", "application/octet-stream");
xhr.setRequestHeader("X-File-Name", encodeURIComponent(file.name));
xhr.setRequestHeader("X-File-Size", totalSize);
xhr.setRequestHeader("X-Start-Byte", startByte);
xhr.setRequestHeader("X-End-Byte", endByte);
var slice = file.slice(startByte, endByte);
console.log(slice);
xhr.send(slice);
}
</script>


public class FileController : Controller
{

private const string UploadDirectory = "uploads";
[HttpPost]
public async Task<IActionResult> Upload()
{
// 获取上传文件的信息
var fileName = Request.Headers["X-File-Name"];
var fileSize = Convert.ToInt64(Request.Headers["X-File-Size"]);
var startByte = Convert.ToInt64(Request.Headers["X-Start-Byte"]);
var endByte = Convert.ToInt64(Request.Headers["X-End-Byte"]);

// 确定上传文件的保存路径
var uploadPath = Path.Combine(Directory.GetCurrentDirectory(), UploadDirectory);
if (!Directory.Exists(uploadPath))
{
Directory.CreateDirectory(uploadPath);
}

var filePath = Path.Combine(uploadPath, fileName);

// 检查是否为新文件
if (startByte == 0)
{
// 如果是新文件,则创建文件并保存数据
using (var fileStream = new FileStream(filePath, FileMode.Create))
{
await Request.Body.CopyToAsync(fileStream);
}
}
else
{
// 如果不是新文件,则在已有文件的基础上追加数据
using (var fileStream = new FileStream(filePath, FileMode.Append))
{
await Request.Body.CopyToAsync(fileStream);
}
}

// 检查上传进度
if (endByte >= fileSize - 1)
{
// 如果上传完成,则返回成功响应
return Ok();
}
else
{
// 如果未上传完成,则返回下一次上传的起始字节和终止字节
return StatusCode((int)HttpStatusCode.PartialContent, new
{
StartByte = endByte + 1,
EndByte = Math.Min(endByte + 1024 * 1024, fileSize - 1)
});
}
}
}

 

参考文章:http://blog.ncmem.com/wordpress/2023/12/20/net-ajax%e5%a4%a7%e6%96%87%e4%bb%b6%e6%96%ad%e7%82%b9%e7%bb%ad%e4%bc%a0/

欢迎入群一起讨论

 

 

标签:断点续传,endByte,文件,xhr,传输,Ajax,var,Net,上传
From: https://www.cnblogs.com/songsu/p/17915849.html

相关文章

  • ml.net例子笔记4-ml.net v2版本例子运行
    1Ml.NET版本更新当前的Microsoft.ML的软件版本如下:https://gitee.com/mirrors_feiyun0112/machinelearning-samples.zh-cn例子使用版本为1.6.0例子工程更换版本的办法:1Directory.Build.propsnuget.config修改samples目录下文件Directory.Build.props的内容~~~~*......
  • 界面控件DevExpress v23.2全新发布 - 官宣正式支持.NET 8
    DevExpress拥有.NET开发需要的所有平台控件,包含600多个UI控件、报表平台、DevExpressDashboardeXpressApp框架、适用于VisualStudio的CodeRush等一系列辅助工具。屡获大奖的软件开发平台DevExpress今年第一个重要版本v23.1正式发布,该版本拥有众多新产品和数十个具有高影响力......
  • 使用网关采集modbus设备数据转换成profinet协议的方案
    1 方案描述这个方案是使用vfbox网关采集modbus设备的数据,然后转换成profinet协议发送给平台。这种转换方法只需要简单的配置网关参数,不需要进行软件编程,很方便的就把modbus数据转换成了profinet协议。在电脑上通过软件配置网关参数,告诉网关要采集的数据的寄存器地址,然后在配置一下......
  • vue3如何实现断点续传
    首先创建一个vue3项目普通上传//template<inputtype="file"ref="uploadRef"@change="upload"/>//jssetupfunctionupload(event){letfiles=event.target.filesletformData=newFormData()formData.append("file",file......
  • 经典卷积神经网络LeNet&AlexNet&VGG
    LeNetLeNet-5是一种经典的卷积神经网络结构,于1998年投入实际使用中。该网络最早应用于手写体字符识别应用中。普遍认为,卷积神经网络的出现开始于LeCun等提出的LeNet网络,可以说LeCun等是CNN的缔造者,而LeNet则是LeCun等创造的CNN经典之作网络结构图由下图所示: LeNet网络总共有......
  • Netty使用CompletableFuture实现异步串行队列
    一、前言CompletableFuture是JDK1.8提供的一种更加强大的异步编程的api。它实现了Future接口,也就是Future的功能特性CompletableFuture也有。它也实现了CompletionStage接口,CompletionStage接口定义了任务编排的方法,执行某一阶段,可以向下执行后续阶段。CompletableFuture相比于Futu......
  • jQuery与JavaScript与ajax三者的区别与联系
    简单总结:1、JS是一门前端语言。2、Ajax是一门技术,它提供了异步更新的机制,使用客户端与服务器间交换数据而非整个页面文档,实现页面的局部更新。3、jQuery是一个框架,它对JS进行了封装,使其更方便使用。jQuery使得JS与Ajax的使用更方便 关系比喻:若把js比作木头,那么jquery就是......
  • .NET MVC 短信验证码过程
    原文链接:https://blog.csdn.net/weixin_44481764/article/details/979419841:创建一个项目用来调用第三方的类,右键Nuget添加第三方的引用类库qcloudsms_csharp2:把第三方的公共类放入到我们的项目里usingqcloudsms;usingqcloudsms_csharp.httpclient;usingqcloudsms_cshar......
  • WiMinet 评说1.2:多跳无线网络的困境
    1、前言    在工业应用中,低速率,大规模和长距离的无线自组织网络一直没有得到广泛的部署,根本原因在于其稳定性,可靠性和实时性一直无法得到良好的保证。在这种自组织网络中,节点之间的跳转关系大多是根据其相对位置和信号强度来决定的;由于安装位置,部署密度,启动时间等差异,其网......
  • Vue+Node实现大文件上传和断点续传
    源代码断点续传、分片上传、秒传、重试机制文件上传是开发中的难点,大文件上传及断点续传难点中的细节及核心技术点。 element-ui框架的上传组件,是默认基于文件流的。数据格式:form-data;传递的数据:file文件流信息;filename文件名字通过fileRead.readAsDataURL(file)......