zoukankan      html  css  js  c++  java
  • 【翻译】Tusdotnet中文文档(1)配置和用法

    TUSDOTNET

    Tusdotnet是tus协议的一个dotnet实现。tus协议是用来规范文件上传的整个过程,tus基于http协议,规定了一些上传过程中的头部(headers)和对上传过程的描述。它实现了文件的断点恢复上传以及其他的一些实用的规范。我前面文章中,有关于tus的详细文档。在对tusdotnet文档的翻译过程中,我删除了关于IIS的章节,因为IIS的章节单独放在一章中,所以删除IIS对于其他章节没有任何影响。因为我本人从来不会将.net core的项目部署到IIS上。

    Tusdotnet的官方文档在这里:https://github.com/tusdotnet/tusdotnet/wiki

    本章按照如下目录进行翻译:

    配置

    • 总体配置
    • 跨域请求处理

    用法

    • 创建文件之前检查文件的元数据
    • 文件上传完成后的处理
    • 下载文件
    • 删除过期的未完成文件

    总体配置

    tusdotnet使用下面的方式很容易配置:

    app.UseTus(context => new DefaultTusConfiguration {... });

    上述代码中提供的工厂(context => new ...)会作用于每一个请求上。通过检查传入的HttpContext/IOwinRequest,可以为不同的客户机返回不同的配置。

    工厂返回的是一个单利的DefaultTusConfiguration实例,这个实例包含如下属性:

    复制代码
    public class DefaultTusConfiguration
    {
        /// <summary>
        /// 用于监听上传的URL路径 (比如 "/files").
        ///如果站点位于子路径中(例如https://example.org/mysite),也必须包含它(例如/mysite/files)。
        /// </summary>
        public virtual string UrlPath { get; set; }
    
        /// <summary>
        /// The store to use when storing files.
        /// </summary>
        public virtual ITusStore Store { get; set; }
    
        /// <summary>
        /// Callbacks to run during different stages of the tusdotnet pipeline.
        /// </summary>
        public virtual Events Events { get; set; }
    
            /// <summary>
            /// The maximum upload size to allow. Exceeding this limit will return a "413 Request Entity Too Large" error to the client.
            /// Set to null to allow any size. The size might still be restricted by the web server or operating system.
            /// This property will be preceded by <see cref="MaxAllowedUploadSizeInBytesLong" />.
            /// </summary>
            public virtual int? MaxAllowedUploadSizeInBytes { get; set; }
    
            /// <summary>
            /// The maximum upload size to allow. Exceeding this limit will return a "413 Request Entity Too Large" error to the client.
            /// Set to null to allow any size. The size might still be restricted by the web server or operating system.
            /// This property will take precedence over <see cref="MaxAllowedUploadSizeInBytes" />.
            /// </summary>
            public virtual long? MaxAllowedUploadSizeInBytesLong { get; set; }
    
        /// <summary>
        /// Set an expiration time where incomplete files can no longer be updated.
        /// This value can either be <code>AbsoluteExpiration</code> or <code>SlidingExpiration</code>.
        /// Absolute expiration will be saved per file when the file is created.
        /// Sliding expiration will be saved per file when the file is created and updated on each time the file is updated.
        /// Setting this property to null will disable file expiration.
        /// </summary>
        public virtual ExpirationBase Expiration { get; set; }
    }
    复制代码

    根据所使用的存储类型,可能还需要对存储进行一些配置。tusdotnet附带的磁盘存储需要一个目录路径,以及是否应该在连接(指concatenation扩展)时删除“部分(指Upload-Concat:partial)”文件。

    Store = new TusDiskStore(@"C:	usfiles", deletePartialFilesOnConcat: true)

    在上面的例子中,C: usfiles是保存所有文件的地方,deletePartialFilesOnConcat: true表示,一旦创建了最终文件(Upload-Concat:final),就应该删除部分文件(仅由连接扩展(concatenation extension)使用)。默认值为false,因此不会意外删除任何文件。如果不确定,或者没有使用连接扩展,则将其设置为false。有关详细信息,请参见Custom data store -> ITusConcatenationStore.

    跨域请求处理

    为了能够让浏览器通过不同域来上传文件,你需要个体tusdotnet配置跨域请求的相关设置。

    关于跨域的配置非常简单:

    复制代码
    public void ConfigureServices(IServiceCollection services)
    {
        services.AddCors();
    }
    
    public void Configure(IApplicationBuilder app, IHostingEnvironment env, ILoggerFactory loggerFactory)
    {
        app.UseCors(builder => builder
                    .AllowAnyHeader()
                    .AllowAnyMethod()
                    .AllowAnyOrigin()
                    .WithExposedHeaders(tusdotnet.Helpers.CorsHelper.GetExposedHeaders())
            );
        app.UseTus(...);
    }
    复制代码

    在创建文件之前检查文件的元数据

    OnBeforeCreate事件用来在创建文件之前检查文件的元数据

    OnBeforeCreate事件在创建文件之前触发。

    在传递给回调函数的BeforeCreateContext上调用FailRequest将使用400错误码来拒绝请求。多次调用FailRequest将串联/连接错误消息。

    复制代码
    app.UseTus(context => new DefaultTusConfiguration
    {
        UrlPath = "/files",
        Store = new TusDiskStore(@"C:	usfiles"),
        Events = new Events
        {
            OnBeforeCreateAsync = ctx =>
            {
                if (!ctx.Metadata.ContainsKey("name"))
                {
                    ctx.FailRequest("name metadata must be specified. ");
                }
    
                if (!ctx.Metadata.ContainsKey("contentType"))
                {
                    ctx.FailRequest("contentType metadata must be specified. ");
                }
    
                return Task.CompletedTask;
            }
    });
    复制代码

     文件上传完成后的处理

    OnFileCompleteAsync事件用于文件上传完成后的处理

    该事件会在文件上传完成后触发。

    复制代码
    app.UseTus(request => new DefaultTusConfiguration
    {
        Store = new TusDiskStore(@"C:	usfiles"),
        UrlPath = "/files",
        Events = new Events
        {
            OnFileCompleteAsync = async ctx =>
            {
                // ctx.FileId is the id of the file that was uploaded.
                // ctx.Store is the data store that was used (in this case an instance of the TusDiskStore)
    
                // A normal use case here would be to read the file and do some processing on it.
                var file = await ((ITusReadableStore)ctx.Store).GetFileAsync(ctx.FileId, ctx.CancellationToken);
                var result = await DoSomeProcessing(file, ctx.CancellationToken);
    
                if (!result.Success)
                {
                    throw new MyProcessingException("Something went wrong during processing");
                }
            }
        }
    });
    复制代码

    下载文件

    由于tus规范不包含下载文件tusdotnet将自动将所有GET请求转发给下一个中间件,因此开发人员可以选择允许文件下载。

    下面的示例要求数据存储实现ITusReadableStore (TusDiskStore实现了)。如果没有,就必须找出文件的存储位置,并以其他方式读取它们。

    app.Use(async (context, next) =>
                {
                    // /files/ is where we store files
                    if (context.Request.Uri.LocalPath.StartsWith("/files/", StringComparison.Ordinal))
                    {
                        // Try to get a file id e.g. /files/<fileId>
                        var fileId = context.Request.Uri.LocalPath.Replace("/files/", "").Trim();
                        if (!string.IsNullOrEmpty(fileId))
                        {
                            var store = new TusDiskStore(@"C:	usfiles");
                            var file = await store.GetFileAsync(fileId, context.Request.CallCancelled);
    
                            if (file == null)
                            {
                                context.Response.StatusCode = 404;
                                await context.Response.WriteAsync($"File with id {fileId} was not found.", context.Request.CallCancelled);
                                return;
                            }
    
                            var fileStream = await file.GetContentAsync(context.Request.CallCancelled);
                            var metadata = await file.GetMetadataAsync(context.Request.CallCancelled);
    
                            // The tus protocol does not specify any required metadata.
                            // "contentType" is metadata that is specific to this domain and is not required.
                            context.Response.ContentType = metadata.ContainsKey("contentType")
                                ? metadata["contentType"].GetString(Encoding.UTF8)
                                : "application/octet-stream";
    
                            if (metadata.ContainsKey("name"))
                            {
                                var name = metadata["name"].GetString(Encoding.UTF8);
                                context.Response.Headers.Add("Content-Disposition", new[] { $"attachment; filename="{name}"" });
                            }
    
                            await fileStream.CopyToAsync(context.Response.Body, 81920, context.Request.CallCancelled);
                            return;
                        }
                    }

    删除过期的未完成的文件

    如果正在使用的存储支持ITusExpirationStore (TusDiskStore支持),则可以指定未在指定时间段内更新的不完整文件应该标记为过期。如果在ITusConfiguration上设置了过期属性(Expiration-Property),并且存储支持ITusExpirationStore,则tusdotnet将自动执行此操作。但是文件不会自动删除。为了帮助删除过期的不完整文件,ITusExpirationStore接口公开了两个方法,GetExpiredFilesAsync和DeleteExpiredFilesAsync。前者用于获取已过期文件的id列表,后者用于删除过期文件。

    如上所述,tusdotnet不会自动删除过期的文件,所以这需要开发人员来实现。建议在web应用程序添加合适的端点(EndPoint)来运行你自己的代码。这些代码是用诸如crontab之类的工具(比如HangFire)来轮询(或者其他的方式)删除过期未完成上传的文件。

    示例程序:

    IEnumerable<string> expiredFileIds = await tusDiskStore.GetExpiredFilesAsync(cancellationToken);
    // Do something with expiredFileIds.
    int numberOfRemovedFiles = await tusDiskStore.RemoveExpiredFilesAsync(cancellationToken);
    // Do something with numberOfRemovedFiles.

    本篇完。

  • 相关阅读:
    第9章 垄断市场中的企业决策
    第8章 完全竞争市场中的企业决策
    第7章 生产产出的决策分析
    第6章 成本分析
    第5章 生产要素投入的决策分析
    C++_函数指针的内容和应用
    大数据的框架-流程梳理
    数字图像处理_基本概念
    C++_项目开发与Cmake构建工具
    终端--通信和传输协议
  • 原文地址:https://www.cnblogs.com/pangjianxin/p/11177671.html
Copyright © 2011-2022 走看看