.NET 7.0或.NET Core Web APi基于tus协议实现断点续传上传大文件

  • .NET 7.0或.NET Core Web APi基于tus协议实现断点续传上传大文件已关闭评论
  • 28 次浏览
  • A+
所属分类:.NET技术
摘要

关于此协议实现原理这里不做阐述,请参照上述github地址自行了解,本文只给出相关的代码,仅供参考!


.NET 7.0或.NET Core Web APi基于tus协议实现断点续传上传大文件

【导读】前几天由于看到网上的断点续传的文章,也不能说是同出一辙,那简直一模一样,于是有了此文章,不会的童鞋可以上GIthub上查看DEMO。
  1. 基于tus协议实现断点续传演示

.NET 7.0或.NET Core Web APi基于tus协议实现断点续传上传大文件

  1. 基于tus协议前端脚本

关于此协议实现原理这里不做阐述,请参照上述github地址自行了解,本文只给出相关的代码,仅供参考!

<link  href="~/lib/layui/css/layui.css" rel="stylesheet"/> <script src="~/lib/layui/layui.min.js"></script> <script src="~/lib/jquery/dist/jquery.min.js"></script> <script src="~/lib/tus-js-client/dist/tus.min.js"></script>  <div class="form-horizontal" style="margin:100px auto;text-align:center;"> 	<div class="form-group" id="progress-group" style="display:block;"> 		<div id="size"></div> 		<div class="progress"> 			<div id="progress" class="progress-bar progress-bar-success progress-bar-animated progress-bar-striped" role="progressbar" 				 aria-valuemin="0" aria-valuemax="100"> 				<span id="percentage"></span> 			</div> 		</div> 	</div> 	<div class="form-group" style="margin-top: 15px;"> 		<div class="row"> 			<div class="input-group"> 				<input name="file" id="file" type="file" class="form-control" aria-describedby="file" aria-label="Upload"> 				<button class="btn btn-outline-secondary" type="button" id="upload">上传</button> 				<button class="btn btn-outline-danger" type="button" id="pause">暂停</button> 				<button class="btn btn btn-outline-info" type="button" id="continue">继续</button> 			</div> 		</div> 	</div> </div> 

.NET 7.0或.NET Core Web APi基于tus协议实现断点续传上传大文件

  1. 接下来就是我们的js代码,引入tus脚本包和相关的js文件就可以了。
<script> 	$(function () { 		 		layui.use(['layer', 'util'], function () { 			var layer = layui.layer, 			util = layui.util;  			var upload;  			//上传 			$('#upload').click(function () {  				$('#progress-group').show();  				 				var fileInput = $('#file').get(0).files[0];  				if (!fileInput) { 					layer.msg("请选择上传文件!"); 					return; 				}   				if (upload) { 					layer.msg("已经选择过上传文件啦!"); 					return; 				}  				// 创建tus上传对象 				upload = new tus.Upload($('#file')[0].files[0], { 					// 文件服务器上传终结点地址设置 					endpoint: "uploadfile/", 					// 重试延迟设置 					retryDelays: [0, 3000, 5000, 10000, 20000], 					// 附件服务器所需的元数据 					metadata: { 						name: file.name, 						contentType: file.type || 'application/octet-stream', 						emptyMetaKey: '' 					}, 					// 回调无法通过重试解决的错误 					onError: function (error) { 						console.log("Failed because: " + error) 					}, 					// 上传进度回调 					onProgress: onProgress, 					// 上传完成后回调 					onSuccess: function () { 						layer.msg("上传成功,文件名:" + upload.file.name); 						console.log("Download %s from %s", upload.file.name, upload.url) 						upload=undefined; 					} 				})  				upload.findPreviousUploads().then((previousUploads) => {  					var chosenUpload = askToResumeUpload(previousUploads);  					if (chosenUpload) { 						upload.resumeFromPreviousUpload(chosenUpload); 					}  					upload.start(); 				});   				// upload.start() 			});  			//暂停 			$('#pause').click(function () { 				if (!upload) { 					layer.msg("请先开始上传!") 					return; 				} 				if (upload._aborted) { 					layer.msg("已经暂停上传啦!") 					return; 				} 				upload.abort() 				console.log(upload._aborted) 			});  			//继续 			$('#continue').click(function () { 				if (!upload) { 					layer.msg("请先开始上传!") 					return; 				} 				if (!upload._aborted) { 					layer.msg("请先暂停上传!") 					return; 				} 				upload.start() 				console.log(upload._aborted) 			});  			function askToResumeUpload(previousUploads) { 				if (previousUploads.length === 0) return null;  				console.log(previousUploads);  				var text = "系统查询到您之前上传过此文件是否恢复上传?:nn"; 				previousUploads.forEach((previousUpload, index) => { 					text += "[" + index + "] " + util.toDateString(previousUpload.creationTime) + "n"; 				}); 				text += "n输入相应的号码恢复上传或按“取消”键重新上传";  				var answer = prompt(text); 				var index = parseInt(answer, 10);  				if (!isNaN(index) && previousUploads[index]) { 					return previousUploads[index]; 				} 			}  			//上传进度展示 			function onProgress(bytesUploaded, bytesTotal) { 				var percentage = (bytesUploaded / bytesTotal * 100).toFixed(2); 				$('#progress').attr('aria-valuenow', percentage); 				$('#progress').css('width', percentage + '%');  				$('#percentage').html(percentage + '%');  				var uploadBytes = byteToSize(bytesUploaded); 				var totalBytes = byteToSize(bytesTotal);  				$('#size').html(uploadBytes + '/' + totalBytes); 			}  			//将字节转换为Byte、KB、MB等 			function byteToSize(bytes, separator = '', postFix = '') { 				if (bytes) { 					const sizes = ['Bytes', 'KB', 'MB', 'GB', 'TB']; 					const i = Math.min(parseInt(Math.floor(Math.log(bytes) / Math.log(1024)).toString(), 10), sizes.length - 1); 					return `${(bytes / (1024 ** i)).toFixed(i ? 1 : 0)}${separator}${sizes[i]}${postFix}`; 				} 				return 'n/a'; 			}   		});   		  	}); </script> 
  1. 我们创建一个新项目,引用一个tus包 tusdotnet

.NET 7.0或.NET Core Web APi基于tus协议实现断点续传上传大文件

  1. 接下来就是添加中间件,并且配置我们的tus,这里我只实现了相关文件上传后的处理,以及上传文件后垃圾文件回收处理。
private static DefaultTusConfiguration CreateTusConfiguration(WebApplicationBuilder builder)         {             var env = builder.Environment.WebRootPath;              //文件上传路径             var tusFiles = Path.Combine(env, "tusfiles");              if (!Directory.Exists(tusFiles))             {                 Directory.CreateDirectory(tusFiles);             }              return new DefaultTusConfiguration() {                 UrlPath= "/uploadfile",                 //文件存储路径                 Store = new TusDiskStore(tusFiles),                 //元数据是否允许空值                 MetadataParsingStrategy = MetadataParsingStrategy.AllowEmptyValues,                 //文件过期后不再更新                 Expiration = new AbsoluteExpiration(TimeSpan.FromMinutes(5)),                 //事件处理(各种事件,满足你所需)                 Events = new Events                 {                     //上传完成事件回调                     OnFileCompleteAsync = async ctx =>                     {                         //获取上传文件                         var file = await ctx.GetFileAsync();                          //获取上传文件元数据                         var metadatas = await file.GetMetadataAsync(ctx.CancellationToken);                          //获取上述文件元数据中的目标文件名称                         var fileNameMetadata = metadatas["name"];                          //目标文件名以base64编码,所以这里需要解码                         var fileName = fileNameMetadata.GetString(Encoding.UTF8);                          var extensionName = Path.GetExtension(fileName);                          //将上传文件转换为实际目标文件                         File.Move(Path.Combine(tusFiles, ctx.FileId), Path.Combine(tusFiles, $"{ctx.FileId}{extensionName}"));                          var terminationStore = ctx.Store as ITusTerminationStore;                         await terminationStore!.DeleteFileAsync(file.Id, ctx.CancellationToken);                      }                 }             };         } 

使用我们的tus服务

 // 配置tus 服务   app.UseTus(context=> CreateTusConfiguration(builder)); 

配置上传大小

            builder.WebHost.ConfigureKestrel((context, options) =>             {                 options.Limits.MaxRequestBodySize = long.MaxValue;             }); 

GIthub Demo:yeuxuan/tusdemo: C# 断点续传 .NET7.0 WEB TUS (github.com)