【翻譯】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:\tusfiles\", deletePartialFilesOnConcat: true)

在上面的例子中,C:\tusfiles\是保存所有文件的地方,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:\tusfiles\"),
    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:\tusfiles\"),
    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:\tusfiles\");
                        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.

本篇完。


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM