0、寫在前面
原本的文件上傳下載都是自己結合網上的代碼實現的,用起來擴展性不強,性能也不行。
后來發現才知道有這種造好的輪子。擴展性強,性能也強。
1、技術原理
原理大概就是這張圖了。其中tracker和storage需要使用docker安裝,client有基於各種語言的實現,大概就是個接口文件。
2、安裝fastdfs
安裝完成的storage docker自帶nginx,默認開啟8888端口
#docker搜索文件 docker search fastdfs #拉取官方 docker pull delron/fastdfs #查看鏡像 docker images #使用docker鏡像構建tracker容器(跟蹤服務器,起到調度的作用)
docker run -d --network=host --name tracker -v /var/fdfs/tracker:/var/fdfs delron/fastdfs tracker
#使用docker鏡像構建storage容器(存儲服務器,提供容量和備份服務)
docker run -d --network=host --name storage -e TRACKER_SERVER=ip:22122 -v /var/fdfs/storage:/var/fdfs -e GROUP_NAME=group1 delron/fastdfs storage
3、安裝fdfs-client-py
1.先安裝依賴包mutagen、requests
2.直接安裝會報錯,官方下載壓縮包 https://github.com/JaceHo/fdfs_client-py
3.打開 storage_client.py 注釋 12行 如圖所示:
4.把fdfs_client文件夾直接復制到python環境的lib文件夾里
4、在python中連接使用fastdfs
conf文件需要改動兩處,base_path=日志存放路徑,tracker_server=服務器IP:22122

# connect timeout in seconds # default value is 30s # Note: in the intranet network (LAN), 2 seconds is enough. connect_timeout = 5 # network timeout in seconds # default value is 30s network_timeout = 60 # the base path to store log files base_path = C://Users//Administrator//Desktop//py//test//test1 # tracker_server can ocur more than once for multi tracker servers. # the value format of tracker_server is "HOST:PORT", # the HOST can be hostname or ip address, # and the HOST can be dual IPs or hostnames seperated by comma, # the dual IPS must be an inner (intranet) IP and an outer (extranet) IP, # or two different types of inner (intranet) IPs. # for example: 192.168.2.100,122.244.141.46:22122 # another eg.: 192.168.1.10,172.17.4.21:22122 tracker_server = 61.6.192.148:22122 #tracker_server = 192.168.0.197:22122 #standard log level as syslog, case insensitive, value list: ### emerg for emergency ### alert ### crit for critical ### error ### warn for warning ### notice ### info ### debug log_level = info # if use connection pool # default value is false # since V4.05 use_connection_pool = false # connections whose the idle time exceeds this time will be closed # unit: second # default value is 3600 # since V4.05 connection_pool_max_idle_time = 3600 # if load FastDFS parameters from tracker server # since V4.05 # default value is false load_fdfs_parameters_from_tracker = false # if use storage ID instead of IP address # same as tracker.conf # valid only when load_fdfs_parameters_from_tracker is false # default value is false # since V4.05 use_storage_id = false # specify storage ids filename, can use relative or absolute path # same as tracker.conf # valid only when load_fdfs_parameters_from_tracker is false # since V4.05 storage_ids_filename = storage_ids.conf #HTTP settings http.tracker_server_port = 80 #use "#include" directive to include HTTP other settiongs ##include http.conf
from fdfs_client.client import Fdfs_client client = Fdfs_client('C:\\Users\\Administrator\\Desktop\\py\\test\\test1\\client.conf') ret = client.upload_by_filename('C:\\Users\\Administrator\\Desktop\\py\\test\\test1\\zzzz.jpg') print(ret)
5、在Flask中使用fastdfs
# -*- coding: UTF-8 -*- from flask import Flask,render_template,request,send_file from fdfs_client.client import Fdfs_client import io app = Flask(__name__) def getFileExt(filename): return ('%s' % filename.split('.')[-1]).lower() @app.route('/') def index(): return render_template('index.html') #上傳,通用下載,適用於圖片等公開的文件 @app.route('/upload',methods=['GET','POST']) def upload(): print(request.files['_file']) saved_file_name = request.files['_file'].filename client = Fdfs_client('C:\\Users\\Administrator\\Desktop\\py\\test\\test1\\client.conf') #二進制存儲 ret = client.upload_by_buffer(request.files['_file'].read(),getFileExt(saved_file_name)) saved_file = 'http://61.6.192.148:8888/'+ ret['Remote file_id'] return render_template('index.html',ret=ret,saved_file=saved_file,saved_file_name=saved_file_name) #下載,可在fastfds的storage中的配置文件配置只允許后端訪問,適用於非公開的文件 @app.route('/download/',methods=['GET','POST']) def download(): file_id = request.args['file_id'].replace('\\\\','/') print(file_id) client = Fdfs_client('C:\\Users\\Administrator\\Desktop\\py\\test\\test1\\client.conf') #二進制讀取 saved_file_buffer = client.download_to_buffer(file_id) return send_file(io.BytesIO(saved_file_buffer['Content']), attachment_filename=file_id,) if __name__ == '__main__': app.run(debug=True)

<!DOCTYPE html> <html lang="en"> <head> <meta charset="UTF-8"> <title>Title</title> </head> <body> 文件上傳:<br> <form enctype="multipart/form-data" method="post" action="/upload"> <input type="file" name="_file"/> <input type="submit" name="submit"> </form> <br> <a href="{{ saved_file }}">{{saved_file_name }}</a> <br> {{ ret }} </body> </html>