You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何将Javascript上传的附件发送至Python/Flask后端?集成问题求助

文件上传集成问题:前端无法将文件发送到Flask后端

我编写了文件上传代码,但无法实现JavaScript与Flask的集成。目前前端已成功接收文件,但无法将其发送至后端。以下是我的代码,也尝试过一些方案但问题仍未解决,请求帮助。

JavaScript代码

//DOM
const $ = document.querySelector.bind(document);

//APP
let App = {};
App.init = (function () {
    //Init
    function handleFileSelect(evt) {
        const files = evt.target.files; // FileList object

        //files template
        let template = `${Object.keys(files)
            .map(file =>   `<div class="file file--${file}">
                                <div class="name"><span>${files[file].name}</span></div>
                                    <div class="progress active"></div>
                                    <div class="done">
                                        <a href="" target="_blank">
                                        
                                        </a>
                                    </div>
                                </div>
                            </div>`)
            .join("")}`;

        $("#drop").classList.add("hidden");
        $("footer").classList.add("hasFiles");
        $(".importar").classList.add("active");
        $(".submit").classList.add("active");
        setTimeout(() => {
            $(".list-files").innerHTML = template;
        }, 1000);

        Object.keys(files).forEach(file => {
            let load = 2000 + (file * 2000); // fake load
            setTimeout(() => {
                $(`.file--${file}`).querySelector(".progress").classList.remove("active");
                $(`.file--${file}`).querySelector(".done").classList.add("anim");
            }, load);
        });
    }

    // trigger input
    $("#triggerFile").addEventListener("click", evt => {
        evt.preventDefault();
        $("input[type=file]").click();
    });

    $("#triggerFile2").addEventListener("click", evt => {
        evt.preventDefault();
        $("input[type=file]").click();
    });

    // drop events
    $("#drop").ondragleave = evt => {
        $("#drop").classList.remove("active");
        evt.preventDefault();
    };
    $(`#drop`).ondragover = $("#drop").ondragenter = evt => {
        $("#drop").classList.add("active");
        evt.preventDefault();
    };
    $("#drop").ondrop = evt => {
        $("input[type=file]").files = evt.dataTransfer.files;
        $("footer").classList.add("hasFiles");
        $("#drop").classList.remove("active");
        evt.preventDefault();
    };

    //upload more
    $(".importar").addEventListener("click", () => {
        $(".list-files").innerHTML = "";
        $("footer").classList.remove("hasFiles");
        $(".importar").classList.remove("active");
        $(".submit").classList.remove("active");
        setTimeout(() => {
            $("#drop").classList.remove("hidden");
        }, 500);
    });

    // input change
    $("input[type=file]").addEventListener("change", handleFileSelect);
})();

HTML代码

<form method="post" action="/" enctype="multipart/form-data" id="myForm">
    <header>
        <p>
            <span class="up">up</span>
            <span class="load">load</span>
        </p>
    </header>
    <div class="body" id="drop">
        <i class="fa fa-cloud-upload" aria-hidden="true" id="triggerFile"></i>
        <p id="text-upload" class="pointer-none"><a href="" id="triggerFile2">
            <strong>Browse</strong></a> to begin the upload
        </p>
        <input type="file" multiple="multiple" />
     </div>
     <footer>
         <div class="divider">
             <span>
                 <AR>FILES</AR>
             </span>
         </div>
         <div class="list-files">
             <!--   template   -->
         </div>
         <button class="importar">Clear</button>
         <button class="submit" type="submit" value="Submit""">Submit</button>
      </footer>
</form>

Flask/Python代码

import os
from flask import Flask, flash, request, redirect, render_template
from werkzeug.utils import secure_filename

app=Flask(__name__)

app.secret_key = "secret key"
app.config['MAX_CONTENT_LENGTH'] = 16 * 1024 * 1024

path = os.getcwd()
# file Upload
UPLOAD_FOLDER = os.path.join(path, 'uploads')

if not os.path.isdir(UPLOAD_FOLDER):
    os.mkdir(UPLOAD_FOLDER)

app.config['UPLOAD_FOLDER'] = UPLOAD_FOLDER


ALLOWED_EXTENSIONS = set(['xlsx', 'xls'])


def allowed_file(filename):
    return '.' in filename and filename.rsplit('.', 1)[1].lower() in ALLOWED_EXTENSIONS


@app.route('/')
def upload_form():
    return render_template('index.html')


@app.route('/', methods=['POST'])
def upload_file():
    if request.method == 'POST':
        # check if the post request has the file part
        if 'file' not in request.files:
            flash('No file part')
            return redirect(request.url)
        file = request.files['file']
        if file.filename == '':
            flash('No file selected for uploading')
            return redirect(request.url)
        if file and allowed_file(file.filename):
            filename = secure_filename(file.filename)
            file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
            flash('File successfully uploaded')
            return redirect('/')
        else:
            flash('Allowed file types are txt, pdf, png, jpg, jpeg, gif')
            return redirect(request.url)


if __name__ == "__main__":
    app.run(host = '127.0.0.1',port = 5000, debug = False)

已尝试的方案

  • 基于Ajax的JavaScript文件上传示例
  • JavaScript与Python文件传输方案
  • Flask API文件上传下载指南

问题核心原因及修复方案

1. 文件输入框缺少name属性

Flask后端通过request.files['file']获取上传文件,必须匹配前端文件输入框的name属性。当前HTML中的文件输入框未设置该属性,导致后端无法识别文件字段。

修复:
修改HTML中的文件输入框:

<input type="file" name="file" multiple="multiple" />

2. 提交按钮语法错误

提交按钮的value属性多了一个引号(value="Submit""),会导致HTML解析异常,阻碍表单正常提交。

修复:
修正按钮代码:

<button class="submit" type="submit" value="Submit">Submit</button>

3. 拖拽上传的兼容性问题

直接给input.files赋值evt.dataTransfer.files在部分浏览器中会因安全限制失效,需通过DataTransfer重构并手动触发change事件同步UI。

修复JS拖拽事件:

$("#drop").ondrop = evt => {
    evt.preventDefault();
    const dt = new DataTransfer();
    [...evt.dataTransfer.files].forEach(file => dt.items.add(file));
    $("input[type=file]").files = dt.files;
    // 手动触发change事件更新UI
    $("input[type=file]").dispatchEvent(new Event('change'));
    $("#drop").classList.remove("active");
    $("footer").classList.add("hasFiles");
};

4. 模板需渲染Flash消息

后端flash()返回的提示信息需要在模板中渲染才能显示,否则无法得知提交结果。在index.html中添加:

{% with messages = get_flashed_messages() %}
  {% if messages %}
    {% for message in messages %}
      <div style="color: red; margin: 10px 0;">{{ message }}</div>
    {% endfor %}
  {% endif %}
{% endwith %}

5. 多文件上传的后端适配(可选)

若需支持多文件上传,后端需遍历request.files.getlist('file')而非仅获取单个文件:

修复Flask后端:

@app.route('/', methods=['POST'])
def upload_file():
    if request.method == 'POST':
        if 'file' not in request.files:
            flash('没有文件部分')
            return redirect(request.url)
        files = request.files.getlist('file')
        for file in files:
            if file.filename == '':
                flash('未选择文件')
                return redirect(request.url)
            if file and allowed_file(file.filename):
                filename = secure_filename(file.filename)
                file.save(os.path.join(app.config['UPLOAD_FOLDER'], filename))
        flash('所有文件上传成功')
        return redirect('/')
    flash('请求方法错误')
    return redirect(request.url)

内容的提问来源于stack exchange,提问作者Roberto

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.08.08 18:25:28