Python脚本--Flask 文件上传功能(前后端分离)

偶然在Java开发同事那里看到他们临时项目使用的一个文件上传页面,比我原来写的好看,并且支持拖拽上传、多个文件上传。但它使用Java提供服务,没法直接使用, 简单写了一个Python Flask的后端脚本。

前端页面如下:

Python脚本--Flask 文件上传功能(前后端分离)_第1张图片

目录结构:

        flask_file_upload

          -- static

               -- uploads

                    -- 视频.mp4

          -- app.py

        UI_file_upload

          -- css

              -- style.css

          -- images

          -- scripts

             -- lang.zh-Hans.js

             -- transfer.js

          -- index.html

app.py :

# !usr/bin/python3
# -*- coding=utf-8 -*-
# @File : app.py
# @Time : 2021-07-06

import os
import json
from urllib.parse import quote, unquote
from gevent import monkey
from gevent.pywsgi import WSGIServer
from flask_cors import CORS, cross_origin
from werkzeug.utils import secure_filename
from flask import Flask, \
    Blueprint, \
    request, \
    jsonify, \
    make_response, \
    send_from_directory


monkey.patch_all() # 将python标准的io方法,都替换成gevent中的同名方法,遇到io阻塞gevent自动进行协程切换
app = Flask(__name__)
cors = CORS(app)
app.config['JSON_AS_ASCII'] = False  # 而json.dumps方法需要添加参数 ensure_ascii=False;避免显示中文乱码
# app.config['MAX_CONTENT_LENGTH'] = 1024 * 1024  # 设置上传文件大小

basepath = os.path.dirname(__file__)
UPLOAD_PATH = os.path.join(basepath, r'static\uploads')


# 解析文件大小并分配相应的单位
def allocateUnit(value):
    multiplyFactor = 0
    tokens = ["bytes", "KB", "MB", "GB", "TB"]
    while value > 1024:
        value /= 1024
        multiplyFactor += 1
    if multiplyFactor <= 4:
        tokensUnit = tokens[multiplyFactor]
    return "%s %s" % (round(value, 2), tokensUnit)


@app.route('/files/', methods=["GET", "POST"])
def get_image(filename):
    if request.method == 'GET':
        # filename = quote(filename, "utf-8")  # 若使用 secure_filename, 则必须转换
        response = make_response(send_from_directory(UPLOAD_PATH, filename, as_attachment=True))
        response.headers["Content-Disposition"] = "attachment; filename={}".format(
            filename.encode().decode('latin-1'))
        return response

    if request.method == 'POST':
        # filename = quote(filename, "utf-8")  # 若使用 secure_filename, 则必须转换
        file_path = os.path.join(UPLOAD_PATH, filename)
        os.remove(file_path)
        return jsonify({'data': {'code': 'Delete success !'}}), 200


@app.route('/files/', methods=['POST', 'GET'])
def upload():
    if request.method == 'GET':
        file_list = []
        for root, dirs, files in os.walk(UPLOAD_PATH):
            for f in files:
                f_dict = {}
                f_p = os.path.join(root, f)
                # f_size = round((((os.stat(f_p)).st_size)/1024)/1000, 2)
                f_size = allocateUnit((os.stat(f_p)).st_size)
                f_dict["name"] = unquote(f, "utf-8")
                f_dict["size"] = (f_size)
                file_list.append(f_dict)
        return json.dumps(file_list)

    if request.method == 'POST':
        f = dict(request.form)['fileName']  # f = 2022-%E6%8AE6%9C%AF%E7%%94%E5%8F%91%%AD%E5%BF%83KPI%E8%83%E6%A0%B8%E8%A1%A8.xlsx
        f = unquote(f, "utf-8")  # Uri解码后:f = 2022-03KPI考核表.xlsx
        fname = request.files.get('newfile')

        # 当前文件所在路径; 由于secure_filename 会忽略中文(“2022-03技术KPI考核表.xlsx” 会被更改为 “2022-03KPI.xlsx”),弃用
        # upload_file_path = os.path.join(basepath, r'static\uploads', secure_filename(f))
        upload_file_path = os.path.join(basepath, r'static\uploads', f)

        # print(upload_file_path)  # D:\pythontest\98-test\981-flaskupload\static\uploads\2022-03技术KPI考核表.xlsx
        fname.save(upload_file_path)
        return jsonify({'data': {'code': 'success'}}), 200


if __name__ == '__main__':
    # 将 127.0.0.1 8800 修改为本机的 ip地址即可
    app.run(threaded=True, host="127.0.0.1", port=8800, debug=True)

transfer.js (server_add 按需改为后端服务器的地址):

$(function() {
	var isDragOver = false;
	
	var files = [];
    // server_add 按需改为后端服务器的地址
	var server_add = "http://127.0.0.1:8800/";
	var currentFileName;

	var uploadQueue = [];
	var currentQueueIndex = 0;
	var isUploading = false;
	var getProgressReties = 0;
	
	var html5Uploader = null;
	var items = {};
	
	function initPageStrings() {
		document.title = STRINGS.WIFI_TRANS_TITLE;
		$('.content_title').text(STRINGS.FILES_ON_DEVICE);
		$('.table_header .filename').text(STRINGS.FILENAME);
		$('.table_header .size').text(STRINGS.FILE_SIZE);
		$('.table_header .operate').text(STRINGS.FILE_OPER);
	}
    

lang.zh-Hans.js (Web页面显示的内容和标题,按需更改): 

    

var STRINGS = {};

STRINGS.WIFI_TRANS_TITLE = 'File Upload';
STRINGS.FILES_ON_DEVICE = '您设备上的文件列表';
STRINGS.FILENAME = '文件名';
STRINGS.FILE_SIZE = '大小';
STRINGS.FILE_OPER = '操作';
STRINGS.CONFIRM_DELETE_BOOK = '是否删除文件?';
STRINGS.DOWNLOAD_FILE = '下载文件';
STRINGS.DELETE_FILE = '删除文件';
STRINGS.USE_ONE_BROWSER = '无法上传文件,请勿使用多个浏览器窗口同时上传。';
STRINGS.UPLOAD_FAILED = '上传失败,请重新打开网络 并 刷新此页重新上传。';
STRINGS.UNSUPPORTED_FILE_TYPE = '请选择文件。';
STRINGS.FILE_IN_QUEUE = '文件已经在上传列队中。';
STRINGS.FILE_EXISTS = '文件已存在,请先删除再重新上传。';
STRINGS.YOU_CHOOSE = '您选择了';
STRINGS.CHOSEN_FILE_COUNT = '个文件,只能上传';
STRINGS.VALID_CHOSEN_FILE_COUNT = '个文件。\n请选择文件,文件名不能重复。';
STRINGS.CANCEL = '取消';
STRINGS.SELECT_YOUR_FILES = '请选择您要上传的文件';
STRINGS.SUPPORTED_FILE_TYPES = '支持MP4';
STRINGS.CANNOT_CONNECT_SERVER = '无法连接到服务器,请重新连接网络并刷新此页后重新上传。';
STRINGS.DRAG_TO_HERE = "拖拽到此处上传";
STRINGS.SELECT_BUTTON_LABLE1 = "选择文件";
STRINGS.SELECT_BUTTON_LABLE2 = "可同时上传多个文件";
STRINGS.SELECT_BUTTON_LABLE = "选择文件";
STRINGS.WIFI_AVAILABLE = "网络连接已启用";

STRINGS.FONT_WIFI_TRANS_TITLE = 'WFi 传字体';
STRINGS.FONT_CONFIRM_DELETE_BOOK = '是否删除字体?';
STRINGS.FONT_UNSUPPORTED_FILE_TYPE = '请选择您要上传的TTF或OTF字体文件。';
STRINGS.FONT_SUPPORTED_FILE_TYPES = '支持TTF和OTF';
STRINGS.FONT_VALID_CHOSEN_FILE_COUNT = '个文件。\n请选择TTF或OTF文件,文件名不能重复。';
STRINGS.FONT_FILE_EXISTS = '文件已存在。';
 

前端使用Nginx运行,后端Flask运行即可。

前端:

         下载:https://wwz.lanzoul.com/ijaYH07vaf6f 密码:6wcu

         

你可能感兴趣的:(flask,python,后端)