一日一技:超级简单搭建更加稳定安全的文件分享服务器

  • 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返回。