一日一技:超級簡單搭建更加穩定安全的文件分享伺服器

  • 2020 年 2 月 26 日
  • 筆記

攝影:產品經理

必勝客的披薩比義大利的更符合中國人的口味

在公眾號以前的文章裡面,我們提到,如果想簡單的分享一下文件,我們可以使用一行 Python 命令:

python3 -m http.server  

這條命令會開啟一個文件分享服務,通過在瀏覽器訪問http://ip:8000可以看到運行這條命令的文件夾下面的全部文件。點擊即可下載。如下圖所示:

這種方法,確實簡單。但有3個問題:

  1. 一次只能下載一個文件,如果文件比較大,在下載的過程中其他人無法下載其他文件。
  2. 當前文件夾下面的所有文件都會出現在網頁上,容易導致敏感數據泄露。如果你只想讓別人下載其中一個文件,你需要單獨給這個文件創建一個文件夾,並在這個文件夾裡面執行命令。
  3. 這個簡單的網路服務不穩定。

那有沒有更穩定、安全同時也不太難的方案呢?當然是有,那就是使用 fastapi。

fastapi 基於starlette 開發。而 starlette裡面有一個返回類型叫做FileResponse。使用它,可以非常方便地返迴文件。我們來看看程式碼。

首先安裝三個庫uvicorn/fastapi/aiofiles:

pip install uvicorn  pip install fastapi  pip install aiofiles  

然後編寫程式碼並保存為FileServer.py

import os  from fastapi import FastAPI  from starlette.responses import FileResponse      @app.get('/record/{filename}')  def get_record(filename: str):      path = os.path.join('output', filename)      if not os.path.exists(path):          return {'success': False, 'msg': '文件不存在!'}      response = FileResponse(path)      return response  

其中,我把所有文件都存放在當前文件夾下面的output文件夾中。用戶通過訪問http://ip:埠/record/文件名。服務拿到文件名以後,拼出完整的文件路徑,傳入FileResponse類並回response 對象。

以上就是全部程式碼。非常簡單直觀。

現在我們來運行這個文件服務:

uvicorn FileServer:app --host 0.0.0.0 --port 8888  

這樣,你想分享具體哪個文件,你就構造一個 URL:http://ip:8888/record/文件名發給別人。別人直接訪問這個 URL 就能來下載對應的文件了。只要對方不知道其他文件的文件名,就無法看到或者下載其他文件。

如果想更安全,你還可以給每個文件做一個單獨的文件編號,把編號-地址對應關係存放在資料庫中。用戶請求的時候,傳入的是文件編號,你從資料庫查出文件的真實路徑再通過FileResponse返回。