华域联盟 .Net .NET或.NET Core Web APi基于tus协议实现断点续传的示例

.NET或.NET Core Web APi基于tus协议实现断点续传的示例

.NET或.NET Core Web APi基于tus协议实现断点续传的示例
 更新时间:2020年11月05日 09:51:12   作者:Jeffcky  

这篇文章主要介绍了.NET或.NET Core Web APi基于tus协议实现断点续传的示例,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧

前言
前两天我采用技巧式方案基本实现大文件分片上传,这里只是重点在于个人思路和亲身实践,若在实际生产环境要求比较高的话肯定不行,仍存在一些问题需要深入处理,本文继续在之前基础上给出基于tus协议的轮子方案,本打算再次尝试利用.NET Core实现此协议,但在github上一搜索早在2016年就已有此协议对应的.NET和.NET Core方案,并且一直更新到最近的.NET Core 3.x版本,完全满足各位所需,本文是我写出的一点demo,demo地址:github.com/wangpengxpy/tus-demo
基于tus协议实现断点续传演示

基于tus协议tusdotnet方案基本demo
关于此协议实现原理这里不做阐述,请参照上述github地址自行了解,本文只是给出.NET Core方案下的基本demo,我们上传一个大文件然后通过进度显示上传进度以及对上传可暂停可继续,专业点讲就是断点续传,首先肯定是引入tus脚本和需要用到的bootstrap样式,我们将进度条默认隐藏,当上传时才显示,所以我们给出如下HTML。

<div class="form-horizontal" style="margin-top:80px;">
<div class="form-group" id="progress-group" style="display:none;">
<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">
<div class="col-md-10">
<input name="file" id="file" type="file" />
</div>
</div>
<div class="form-group">
<div class="col-md-offset-2 col-md-10">
<input type="submit" id="submit" value="上传" class="btn btn-success" />
<input type="button" id="pause" value="暂停" class="btn btn-danger" />
<input type="button" id="continue" value="继续" class="btn btn-info" />
</div>
</div>
</div>

接下来就是使用引入的tus脚本,也没什么太多要讲解的,直接上代码,这里稍微注意的是在如下元数据(metadata)属性对象定义给出实际文件名,便于在后台最终将上传的文件转换为目标文件,至少得知道文件扩展名,对吧。

<script type="text/javascript">
$(function () {
var upload;

//上传
$('#submit').click(function () {

$('#progress-group').show();

var file = $('#file')[0].files[0];

// 创建tus上传对象
upload = new tus.Upload(file, {
// 文件服务器上传终结点地址设置
endpoint: "files/",
// 重试延迟设置
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 () {
console.log("Download %s from %s", upload.file.name, upload.url)
}
})

upload.start()
});

//暂停
$('#pause').click(function () {
upload.abort()
});

//继续
$('#continue').click(function () {
upload.start()
});

//上传进度展示
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>

接下来进入后台,首先安装对应tus协议实现包,如下:

接下来则是添加tus中间件,说白了就是对tus的配置,各种配置都可满足你所需,这里我只实现了文件上传完成后将上传文件转换为目标文件的处理,紧接着将如下实现tus配置以单例形式注入即可

private DefaultTusConfiguration CreateTusConfiguration(IServiceProvider serviceProvider)
{
var env = (IWebHostEnvironment)serviceProvider.GetRequiredService(typeof(IWebHostEnvironment));

//文件上传路径
var tusFiles = Path.Combine(env.WebRootPath, "tusfiles");

return new DefaultTusConfiguration
{
UrlPath = "/files",
//文件存储路径
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}"));
}
}
};
}

然后获取并使用上述添加的tus配置服务

app.UseTus(httpContext => Task.FromResult(httpContext.RequestServices.GetService<DefaultTusConfiguration>()));

在脚本中我们看到有个endpoint属性,此属性表示上传到服务器的上传结点地址,因为在上到服务器时我们可能需对此请求进行额外处理,比如元数据中的文件名是否已提供等等,所以我们在使用结点映射时,添加对上述结点名称的映射,如下:

endpoints.MapGet("/files/{fileId}", DownloadFileEndpoint.HandleRoute);

该映射第二个参数为RequestDelegate,这个参数用过.NET Core的童鞋都知道,这里我是直接拷贝该包的路由实现,如下:

public static class DownloadFileEndpoint
{
public static async Task HandleRoute(HttpContext context)
{
var config = context.RequestServices.GetRequiredService<DefaultTusConfiguration>();

if (!(config.Store is ITusReadableStore store))
{
return;
}

var fileId = (string)context.Request.RouteValues["fileId"];
var file = await store.GetFileAsync(fileId, context.RequestAborted);

if (file == null)
{
context.Response.StatusCode = 404;
await context.Response.WriteAsync($"File with id {fileId} was not found.", context.RequestAborted);
return;
}

var fileStream = await file.GetContentAsync(context.RequestAborted);
var metadata = await file.GetMetadataAsync(context.RequestAborted);

context.Response.ContentType = GetContentTypeOrDefault(metadata);
context.Response.ContentLength = fileStream.Length;

if (metadata.TryGetValue("name", out var nameMeta))
{
context.Response.Headers.Add("Content-Disposition",
new[] { $"attachment; filename=\\"{nameMeta.GetString(Encoding.UTF8)}\\"" });
}

using (fileStream)
{
await fileStream.CopyToAsync(context.Response.Body, 81920, context.RequestAborted);
}
}

private static string GetContentTypeOrDefault(Dictionary<string, Metadata> metadata)
{
if (metadata.TryGetValue("contentType", out var contentType))
{
return contentType.GetString(Encoding.UTF8);
}

return "application/octet-stream";
}
}

文件上传大小限制说明
我们知道无论是.NET还是.NET Core对于文件上传大小都有默认限制大小,这里对.NET Core中文件大小各种环境配置做一个统一说明,如果你将.NET Core寄宿在IIS上运行,那么请修改web.config配置文件大小限制

<system.webServer>
<security>
<requestFiltering>
//若不配置,默认是28.6兆
<requestLimits maxAllowedContentLength="1073741824" />
</requestFiltering>
</security>
</system.webServer>

如果在开发环境默认使用IIS运行应用程序,请通过如下根据实际情况配置文件上传大小

services.Configure<IISServerOptions>(options =>
{
options.MaxRequestBodySize = int.MaxValue;
});

如果程序运行在Kestrel服务器,那么请通过如下根据实际情况配置文件上传大小

services.Configure<KestrelServerOptions>(options =>
{
//若不配置,默认是30兆(没记错的话)
options.Limits.MaxRequestBodySize = int.MaxValue;
});

如果是通过表单上传文件,那么请通过如下根据实际情况配置文件上传大小

services.Configure<FormOptions>(x =>
{
x.ValueLengthLimit = int.MaxValue;
//如果不配置,默认是128兆(没记错的话)
x.MultipartBodyLengthLimit = int.MaxValue;
x.MultipartHeadersLengthLimit = int.MaxValue;
});

总结
为了更好体验可以再加上当前网络宽带情况或剩余多少分钟,更详细内容请参考:github.com/tusdotnet/tusdotnet、github.com/tus/tus-js-client,关于大文件上传处理到此结束,希望对那些苦苦寻找最终解决方案而无助的童鞋们提供最佳轮子,谢谢。
到此这篇关于.NET或.NET Core Web APi基于tus协议实现断点续传的示例的文章就介绍到这了,更多相关.NET tus断点续传内容请搜索华域联盟以前的文章或继续浏览下面的相关文章希望大家以后多多支持华域联盟!

您可能感兴趣的文章:在ASP.NET中支持断点续传下载大文件(ZT)源码Asp.net中断点续传的原理与实现方法分享ASP.NET 文件断点续传实现代码

.NET
tus
断点续传

相关文章
在.NET2.0中使用自定义事务操作在.NET2.0中使用自定义事务操作... 2006-09-09
Asp.net在ashx文件中处理Session问题解决方法Asp.net在ashx文件中处理Session问题解决方法,需要的朋友可以参考一下 2013-05-05
asp.net 按指定模板导出word,pdf实例代码这篇文章介绍了asp.net 按指定模板导出word,pdf实例代码,有需要的朋友可以参考一下 2013-09-09
Asp.Net Core 中的“虚拟目录”实现这篇文章主要介绍了Asp.Net Core 中的“虚拟目录”实现,文中通过示例代码介绍的非常详细,对大家的学习或者工作具有一定的参考学习价值,需要的朋友们下面随着小编来一起学习学习吧 2020-08-08
.NET Core 实现定时抓取网站文章并发送到邮箱本片文章通过实例讲述.NET Core 实现定时抓取博客园首页文章信息并发送到邮箱这个功能,对此有兴趣的朋友参考学习下。 2018-02-02
WPF实现渐变淡入淡出的登陆窗口效果这篇文章主要介绍了WPF实现渐变淡入淡出的登陆窗口效果的方法,详细讲述了该效果的实现原理与功能代码,具有一定的参考借鉴价值,需要的朋友可以参考下 2014-11-11
ASP.NET MVC4 HtmlHelper扩展类,实现分页功能本文主要做了一个HtmHelper类的分页扩展函数,方便在视图中调用,有需要的朋友可以参考一下,希望对大家有所帮助。 2016-03-03
ASP.NET 前台javascript与后台代码调用ASP.NET中前台javascript与后台代码调用的实现代码说明。 2009-08-08
使用 Visual Studio 的“代码度量值”来改进代码质量代码度量是一组软件度量值,使开发人员可以更好地了解他们正在开发的代码.这篇文章主要介绍了通过 Visual Studio 的“代码度量值”来改进代码质量,需要的朋友可以参考下 2017-11-11
Gridview使用CheckBox全选与单选采用js实现同时高亮显示选择行Gridview使用CheckBox单选与全选功能再次进行简单演示,选中的行,使用高亮显示,让用户一目了然看到哪一行被选择了,在项目中很实用的,开发中的朋友们可要考虑一下哦 2013-01-01

最新评论

本文由 华域联盟 原创撰写:华域联盟 » .NET或.NET Core Web APi基于tus协议实现断点续传的示例

转载请保留出处和原文链接:https://www.cnhackhy.com/5034.htm

本文来自网络,不代表华域联盟立场,转载请注明出处。

作者:

发表回复

联系我们

联系我们

2551209778

在线咨询: QQ交谈

邮箱: [email protected]

工作时间:周一至周五,9:00-17:30,节假日休息

关注微信
微信扫一扫关注我们

微信扫一扫关注我们

关注微博
返回顶部