自定義功能和相關技術
本篇按照如下結構翻譯
自定義功能
- 自定義數據倉庫
相關技術
- 架構和總體概念
自定義數據倉庫
tusdotnet附帶一個存儲庫TusDiskStore,它將文件保存在磁盤上的一個目錄中。你可以通過實現以下一個或多個接口(在“接口”這一節中列出來的接口)來實現自己的存儲。tusdotnet將自動處理請求並根據用於請求的存儲所實現的接口將信息添加到Tus-Extension頭部。
請注意有一些方法會在請求執行期間多次調用,這取決於倉儲正確的緩存數據。
要實現的最常見接口是ITusStore、ITusCreationStore和ITusReadableStore。這將允許倉儲(store)創建和上傳文件,並讀取文件以進行處理或下載。
接口
以下涉及到的名詞請查看我的關於tus協議的翻譯。
- ITusStore-這個接口支持核心協議
- ITusChecksumStore - 支持Checksum擴展 (checksum verification of files)
- ITusConcatenationStore - 支持Concatenation擴展(merging multiple files together with a single command)
- ITusCreationStore - 支持Creation擴展 (creating new files)
- ITusCreationDeferLength - 支持Upload-Defer-Length頭部 (sub extension of Creation)
- ITusReadableStore - 支持從文件倉儲中讀取文件 (e.g. for downloads or processing)
- ITusTerminationStore - 支持Termination擴展 (deleting files)
- ITusExpirationStore -支持Expiration擴展 (files expire after a period of time)
ITusStore
必須實現的接口,在Tus-Extension中的值:<none>
這是tus核心協議的接口,自定義的倉儲必須實現。
http://tus.io/protocols/resumable-upload.html#core-protocol或請查看我翻譯的tus協議的相關內容。
public interface ITusStore { /// <summary> /// 使用提供的流將數據寫入文件 /// 如果流的長度超過了上傳文件的長度,必須拋出<exception cref="TusStoreException"></exception>異常/// </summary> /// <param name="fileId">要寫入的文件Id</param> /// <param name="stream">來自客戶端的輸入流</param> /// <param name="cancellationToken">取消令牌</param> /// <returns>寫入的字節長度</returns> Task<long> AppendDataAsync(string fileId, Stream stream, CancellationToken cancellationToken); /// <summary> /// 檢索一個文件是否存在 /// </summary> /// <param name="fileId">要檢查的文件Id</param> /// <param name="cancellationToken">取消令牌.</param> /// <returns></returns> Task<bool> FileExistAsync(string fileId, CancellationToken cancellationToken); /// <summary> /// Returns the upload length specified when the file was created or null if Defer-Upload-Lenght was used. /// </summary> /// <param name="fileId">The id of the file to check.</param> /// <param name="cancellationToken">Cancellation token to use when cancelling.</param> /// <returns>The upload length of the file</returns> Task<long?> GetUploadLengthAsync(string fileId, CancellationToken cancellationToken); /// <summary> /// Returns the current size of the file a.k.a. the upload offset. /// </summary> /// <param name="fileId">The id of the file to check.</param> /// <param name="cancellationToken">Cancellation token to use when cancelling.</param> /// <returns>The size of the current file</returns> Task<long> GetUploadOffsetAsync(string fileId, CancellationToken cancellationToken); }
ITusChecksumStore
非必須實現的接口,在Tus-Extension中的值:checksum
支持checksum擴展的接口,用於文件校驗和(checksum)的檢查。
http://tus.io/protocols/resumable-upload.html#checksum 或請查看我翻譯的tus協議的相關內容。
public interface ITusChecksumStore { /// <summary> /// Returns a collection of hash algorithms that the store supports (e.g. sha1). /// </summary> /// <param name="cancellationToken">Cancellation token to use when cancelling</param> /// <returns>The collection of hash algorithms</returns> Task<IEnumerable<string>> GetSupportedAlgorithmsAsync(CancellationToken cancellationToken); /// <summary> /// Verify that the provided checksum matches the file checksum. /// </summary> /// <param name="fileId">The id of the file to check</param> /// <param name="algorithm">The checksum algorithm to use when checking. This algorithm must be supported by the store.</param> /// <param name="checksum">The checksom to use for verification</param> /// <param name="cancellationToken">Cancellation token to use when cancelling</param> /// <returns>True if the checksum matches otherwise false</returns> Task<bool> VerifyChecksumAsync(string fileId, string algorithm, byte[] checksum, CancellationToken cancellationToken); }
ITusConcatenationStore
非必須實現的接口,Tus-Extension中的值:concatenation
注意:要實現這個接口必須保證ITusCreationStore也被實現。
這個接口添加了對concatenation擴展的支持,這個擴展的作用在於在一個POST請求中將多個文件串聯然后得到一個最終文件。
http://tus.io/protocols/resumable-upload.html#concatenation或查看我關於tus協議的相關翻譯
public interface ITusConcatenationStore { /// <summary> /// Returns the type of Upload-Concat header that was used when creating the file. /// Returns null if no Upload-Concat was used. /// </summary> /// <param name="fileId">The file to check</param> /// <param name="cancellationToken">Cancellation token to use when cancelling</param> /// <returns>FileConcatPartial, FileConcatFinal or null</returns> Task<FileConcat> GetUploadConcatAsync(string fileId, CancellationToken cancellationToken); /// <summary> /// Create a partial file. This method is called when a Upload-Concat header is present and when its value is "partial". /// </summary> /// <param name="uploadLength">The length of the upload in bytes</param> /// <param name="metadata">The Upload-Metadata request header or null if no header was provided</param> /// <param name="cancellationToken">Cancellation token to use when cancelling</param> /// <returns>The id of the newly created file</returns> Task<string> CreatePartialFileAsync(long uploadLength, string metadata, CancellationToken cancellationToken); /// <summary> /// Creates a final file by concatenating multiple files together. This method is called when a Upload-Concat header /// is present with a "final" value. /// </summary> /// <param name="partialFiles">List of file ids to concatenate</param> /// <param name="metadata">The Upload-Metadata request header or null if no header was provided</param> /// <param name="cancellationToken">Cancellation token to use when cancelling</param> /// <returns>The id of the newly created file</returns> Task<string> CreateFinalFileAsync(string[] partialFiles, string metadata, CancellationToken cancellationToken); }
ITusCreationStore
非必須實現的接口,Tus-Extension的值為:creation
這個接口處理tus協議的創建擴展,並用於創建文件引用,稍后可以利用tus核心協議,使用這個創建的文件引用將數據上載。
http://tus.io/protocols/resumable-upload.html#creation 或查看我的tus協議的相關翻譯。
public interface ITusCreationStore { /// <summary> /// Create a file upload reference that can later be used to upload data. /// </summary> /// <param name="uploadLength">The length of the upload in bytes</param> /// <param name="metadata">The Upload-Metadata request header or null if no header was provided</param> /// <param name="cancellationToken">Cancellation token to use when cancelling</param> /// <returns></returns> Task<string> CreateFileAsync(long uploadLength, string metadata, CancellationToken cancellationToken); /// <summary> /// Get the Upload-Metadata header as it was provided to <code>CreateFileAsync</code>. /// </summary> /// <param name="fileId">The id of the file to get the header for</param> /// <param name="cancellationToken">Cancellation token to use when cancelling</param> /// <returns>The Upload-Metadata header</returns> Task<string> GetUploadMetadataAsync(string fileId, CancellationToken cancellationToken); }
ITusCreationDeferLengthStore
非必須實現的接口,Tus-Extension中的值: creation-defer-length
注意:要實現這個接口必須保證ITusCreationStore接口同時被實現。
creation-defer-length是creation擴展的子擴展,它允許用戶在不預先知道上傳文件大小的情況下創建文件。
如果實現了這個接口,並且用戶選擇使用這個特性,那么對CreateFileAsync (ITusCreationStore)和CreatePartialFileAsync (ITusConcatenationStore)的調用將使用-1作為文件長度。
http://tus.io/protocols/resumable-upload.html#upload-defer-length或查看我的tus文檔
public interface ITusCreationDeferLengthStore { /// <summary> /// Set the upload length (in bytes) of the provided file. /// </summary> /// <param name="fileId">The id of the file to set the upload length for</param> /// <param name="uploadLength">The length of the upload in bytes</param> /// <param name="cancellationToken">Cancellation token to use when cancelling</param> /// <returns>Task</returns> Task SetUploadLengthAsync(string fileId, long uploadLength, CancellationToken cancellationToken); }
ITusTerminationStore
非必須實現的接口,Tus-Extensions中的值:termination
這個接口支持了tus協議中的termination擴展,用於刪除文件。
http://tus.io/protocols/resumable-upload.html#termination 或查看我的tus文檔
public interface ITusTerminationStore { /// <summary> /// Delete a file from the data store. /// </summary> /// <param name="fileId">The id of the file to delete</param> /// <param name="cancellationToken">Cancellation token to use when cancelling</param> /// <returns>Task</returns> Task DeleteFileAsync(string fileId, CancellationToken cancellationToken); }
ITusReadableStore
非必須實現的接口,Tus-Extension中的值:<none>
ITusReadableStore是一個不屬於tus規范的簡單接口,它用於幫助從數據存儲中讀取數據,使下載文件或處理上傳文件變得更容易。如何使用該接口的示例可以在我之前翻譯的tusdotnet文檔的下載文件小結中找到。或者查看英文文檔:Downloading files
public interface ITusReadableStore { /// <summary> /// Get the file with the specified id. /// Returns null if the file was not found. /// </summary> /// <param name="fileId">The id of the file to get</param> /// <param name="cancellationToken">Cancellation token to use when cancelling</param> /// <returns>The file or null if the file was not found</returns> Task<ITusFile> GetFileAsync(string fileId, CancellationToken cancellationToken); }
ITusExpirationStore
非必須實現的接口,Tus-Extension中的值:expiration
這個接口實現了expiration擴展,用於服務端刪除那些過了一段時間后未完成上傳的文件。過期的文件將通過tusdotnet返回404。服務器仍然可以使用倉儲(store)的方法訪問文件。
http://tus.io/protocols/resumable-upload.html#expiration
https://github.com/smatsson/tusdotnet/wiki/Removing-expired-incomplete-files 介紹了更多關於如何配置文件清理的信息。
public interface ITusExpirationStore { /// <summary> /// Set the expiry date of the provided file. /// This method will be called once during creation if absolute expiration is used. /// This method will be called once per patch request if sliding expiration is used. /// </summary> /// <param name="fileId">The id of the file to update the expiry date for</param> /// <param name="expires">The datetime offset when the file expires</param> /// <param name="cancellationToken">Cancellation token to use when cancelling</param> /// <returns>Task</returns> Task SetExpirationAsync(string fileId, DateTimeOffset expires, CancellationToken cancellationToken); /// <summary> /// Get the expiry date of the provided file (set by <code>SetExpirationAsync</code>). /// If the datetime offset returned has passed an error will be returned to the client. /// If no expiry date exist for the file, this method returns null. /// </summary> /// <param name="fileId">The id of the file to get the expiry date for</param> /// <param name="cancellationToken">Cancellation token to use when cancelling</param> /// <returns></returns> Task<DateTimeOffset?> GetExpirationAsync(string fileId, CancellationToken cancellationToken); /// <summary> /// Returns a list of ids of incomplete files that have expired. /// This method can be used to do batch processing of incomplete, expired files before removing them. /// </summary> /// <param name="cancellationToken">Cancellation token to use when cancelling</param> /// <returns>A list of ids of incomplete files that have expired</returns> Task<IEnumerable<string>> GetExpiredFilesAsync(CancellationToken cancellationToken); /// <summary> /// Remove all incomplete files that have expired. /// </summary> /// <param name="cancellationToken">Cancellation token to use when cancelling</param> /// <returns>The number of files that were removed</returns> Task<int> RemoveExpiredFilesAsync(CancellationToken cancellationToken); }
架構和總體概念
這部分描述了tusdonet的架構和它的總體概念。
tusdotnet包含了三個主要的部分:
- Tus的中間件
- 一個用於配置的對象
- 一個數據存儲庫
Tus中間件
這是負責處理所有請求並返回正確響應的OWIN中間件。中間件的功能取決於所使用的數據存儲所實現的接口。
要設置中間件,請使用UseTus擴展方法並為其提供配置工廠。使用這種方法,tusdotnet支持為不同的請求(例如不同的用戶、租戶等)使用不同的配置。
中間件將轉發它不能處理的所有請求,例如GET請求或其他缺少Tus-Resumable頭的請求。這樣,即使客戶機不支持tus協議,開發人員仍然可以處理上傳。
用於配置的對象
用於配置的對象告訴Tus中間件有哪些選項可用。它目前支持設置要偵聽的URL、要使用的數據存儲和在請求處理期間運行的自定義回調。
相關信息在這里:Configure tusdotnet 或者你可以查看我翻譯的文檔。
數據存儲庫
數據存儲是tusdotnet存儲數據的地方,也是決定運行tusdotnet的服務器功能的地方。存儲庫可以實現許多接口,每個接口都賦予系統更多的功能。tusdotnet附帶了一個存儲庫實現TusDiskStore,這是一個簡單的存儲,將數據保存在服務器磁盤上的文件夾中。支持自定義數據(Custom data stores)存儲。