AspNetCore分散式檔案上傳系統

loogn發表於2019-05-10

曾經做過一個學校的系統,主要用於老師上傳課件和佈置作業,學生學習和提交作業,當時也沒考慮那麼多,上傳的檔案全部都是放在同一個伺服器上了,沒想到幾年過去了,這個系統還一直在用著,長時間上傳的資原始檔使硬碟空間吃緊了,歷史資料還沒法存檔,由於這個契機吧,自己簡單實現了一個檔案分佈上傳的系統。下面稱為ufs。

一、系統架構圖

AspNetCore分散式檔案上傳系統

上圖描述了使用者上傳檔案和訪問檔案的流程走向,系統主要涉及ufs和下面的node。
ufs是web網站或者app上傳的統一介面,ufs根據配置把上傳的檔案分發到某個node上。
node會返回上傳結果給ufs,主要是上傳成功後的檔案url,ufs收到url再返回給上層應用。
上層應用獲取到url可以展示出來或者儲存到資料庫。
當使用者訪問資源的時候,直接從各個node獲取。
當某個node的可用儲存滿了,可以從ufs配置中刪除掉,然後加入新的node,刪除的node只要是服務不關閉,照樣可以訪問上面的檔案,具體配置看下面。

二、ufs配置

{
  "ufs": {
    "allowExts": [".txt", ".jpg", ".jpeg", ".png", ".bmp", ".doc", ".docx", ".xls", ".xlsx", ".ppt", ".pptx", ".pdf"],
    "limitSize": 10485760,
    "accessToken": "123456",
    "downstreams": [
      "http://node1.ufs.timeschip.com"
    ],
    "test": {
      "limitSize": 10485760,
      "accessToken": "abcd"
    }
  }
}

ufs就是node的閘道器,提供了下面這幾個功能配置:

  1. allowExts陣列用於配置可以上傳的檔案型別
  2. limitSize限制檔案上傳的大小
  3. accessToken訪問ufs的令牌
  4. downstreams配置下游node節點

上面配置中,和ufs平級的還有一個test節點,裡面允許的子節點和ufs的子節點是一樣的。目的是為不同的應用提供上傳服務。此處的“test”就是應用名稱,這個名字需要和上層應用約定好,test應用上傳的時候表明是test,就會使用配置檔案中test的配置,如果配置檔案中沒有test這個節點配置,就會使用ufs節點下的預設配置。
這樣的配置方式就像該配置檔案本身(appsettings.json)的載入方式一樣,會使用指定的配置覆蓋預設配置,非常靈活。至於如何呼叫,我們後面再說。

三、ufs.node配置

{
  "ufsNode": {
    "mimeModifiers": [
      {
        "ext": ".htm3",
        "type": "text/html",
        "opt": "add"
      },
      {
        "ext": ".mp4",
        "opt": "remove"
      }
    ],
    "domain": "http://node1.ufs.loogn.com",
    "physicalPath": "D:/WebSite_Core/ufsnode1/upload",
    "virtualPath": "/ufs",
    "cachePeriod": 604800,
    "enableThumbnail": true,
    "thumbnailExts": [
      ".jpg",
      ".png"
    ],
    "allowIPs": [
      "::1",
      "127.0.0.1",
      "122.114.222.186"
    ]
  }
}

node的配置比ufs要多一些,畢竟真正的儲存和訪問功能都在node上:

  1. mimeModifiers陣列可以修改node服務的mime型別,每一項有三個子節點:ext為檔案字尾名,type為對映的ContentType, opt是列舉可取add、remove。
  2. domain為該node服務執行的域名,是上傳檔案url的一部分
  3. physicalPath為上傳的物理路徑,儲存的本地絕對路徑
  4. virtualPath為上傳的虛擬路徑,是上傳檔案url的一部分
  5. cachePeriod過期時間(秒)
  6. enableThumbnail是否啟用縮圖功能
  7. thumbnailExts表示哪些檔案型別可以使用縮圖功能,只能配置圖片格式
  8. allowIPs訪問白名單,即ufs服務的ip地址

當啟用縮率圖功能時,可以在url中加w和h引數來訪問想要的縮圖:
原圖:http://node1.ufs.loogn.com/app1/2019/05/10/abc.png
限寬200:http://node1.ufs.loogn.com/app1/2019/05/10/abc.png?w=200
限高200:http://node1.ufs.loogn.com/app1/2019/05/10/abc.png?h=200
限寬高100*200:http://node1.ufs.loogn.com/app1/2019/05/10/abc.png?w=100&h=200
所有的壓縮都是等比的,圖片不會變形,不管引數怎樣,圖片也不會放大。

從allowIPs配置可以看出,應用層訪問ufs是用過accessToken來驗證的,而ufs訪問node是通過在node中配置允許的ip地址來實現的。
AspNetCore分散式檔案上傳系統

四、應用層呼叫

由於公開的是http介面,所以任何支撐Http的語言都可以使用。

        static async Task<string> UploadFile(string filePath)
        {
            HttpClient httpClient = new HttpClient();
            httpClient.DefaultRequestHeaders.Add("accesstoken", "abcd");
            httpClient.DefaultRequestHeaders.Add("app", "test");
            
            var buffer = File.ReadAllBytes(filePath);
            ByteArrayContent byteArray = new ByteArrayContent(buffer);
            byteArray.Headers.Add("ext", Path.GetExtension(filePath));
            var response = await httpClient.PostAsync("http://ufs.loogn.com/uploadfile", byteArray);

            var result = await response.Content.ReadAsStringAsync();
            return result;
        }

http請求頭部需要傳輸三個引數:

  1. accesstoken為訪問ufs的令牌,對用ufs中的配置
  2. app為指定app的名稱,除了和ufs服務中選擇配置相關,node服務也會在physicalPath目錄下建立app同名目錄,用來存放這個應用上傳的檔案,如果沒有這個引數,node會放入default資料夾
  3. ext為上傳檔案的字尾名,注意,是帶.的(比如:.jpg而不是jpg)

檔案內容通過請求體POST到ufs公開上傳地址/uploadfile,響應的字串是json格式,如下:

{"success":true, "msg":"", "fileUrl":"http://node1.ufs.loogn.com/app1/2019/05/10/abc.png"}

如果上傳失敗,success為false,msg中有錯誤資訊。

五、專案地址

https://gitee.com/loogn/ufs

相關文章