使用js将html文件<input>上传到flask服务器

问题描述 投票:0回答:2

我正在尝试将文件从 JS 前端发送到 Flask 后端。 但我的烧瓶后端似乎没有收到文件。 当进入 Flask 后端 HTML 页面并手动提交时它可以工作,但我希望前端将文件发送到后端。

这是有问题的 JavaScript:

function send() {
    const formData = new FormData();
    const files = document.getElementById("file");
    formData.append("file", files.files[0]);
    const requestOptions = {
        headers: {
            "Content-Type": "multipart/form-data",
        },
        mode: "no-cors",
        method: "POST",
        files: files.files[0],
        body: formData,
    };
    console.log(requestOptions);

    fetch("http://localhost:5000/upload", requestOptions).then(
        (response) => {
            console.log(response.data);
        }
    );
}

export default function App() {
    return (
        <div className="App" id="App">
            <header className="App-header">
                <Button variant="outlined" component="label" size="large">
                    Load Audio
                    <input
                        id="file"
                        type="file"
                        onChange={send}
                        hidden
                    />
                </Button>
            </header>
        </div>
    );
}

这是用于处理传入请求的 Flask Python 脚本:

@app.route("/upload", methods=["GET", "POST"])
def upload():
    if request.method == 'POST':
        if 'file' not in request.files:
            print(1)
            flash('No file part')
            return redirect(request.url)
        file = request.files['file']
        if file.filename == '':
            print(2)
            flash('No selected file')
            return redirect(request.url)
        if file and allowed_file(file.filename):
            print(3)
            filename = secure_filename(file.filename)
            session["id"] = filename
            file.save(os.path.join('UPLOAD', filename))
            return redirect(url_for('uploaded',
                                    filename=filename))

    return render_template('upload.html')

打印 1,因此没有找到文件。

如果它有用,这是一个使用

print(request.headers)
进行的调试:

Host: localhost:5000
Connection: keep-alive
Sec-Ch-Ua: "Chromium";v="88", "Google Chrome";v="88", ";Not A Brand";v="99"
Sec-Ch-Ua-Mobile: ?0
Content-Type: multipart/form-data
Accept: */*
Origin: http://localhost:3000
Sec-Fetch-Site: same-site
Sec-Fetch-Mode: no-cors
Sec-Fetch-Dest: empty
Referer: http://localhost:3000/
Accept-Encoding: gzip, deflate, br

我在网上阅读了很多有关如何在这种情况下上传文件的信息,但我无法使其工作。 如果能得到一些帮助那就太好了!

javascript python flask frontend backend
2个回答
1
投票

Flask 中的文件处理似乎恰到好处。 然而,您指定

Content-Type
标头的方式对于 Flask 来说似乎很模糊。

在运行代码的简化示例时,我尝试通过以下方式使用 cURL 对其进行测试:

curl -XPOST http://localhost:5000/upload -F [email protected]

这样 Flask 就知道文件已上传,我就可以在

request.files
中看到它:

ipdb> request.files
ImmutableMultiDict([('file', <FileStorage: 'TestFile.txt' ('text/plain')>)])

还引起我注意的是

Content-Type
指定了边界

('Content-Type', 'multipart/form-data; boundary=------------------------aa8098f7b7fa6c61')

这让我认为手动指定

Content-Type: multipart/form-data
似乎不起作用。

由于您正在尝试通过 JS 进行上传

fetch
,请考虑查看这里。他们也不建议手动设置标题。


1
投票

我发现了另一个修复,正如 @Icebreaker454 所解释的,它与内容类型有关。

如果手动设置的Content-Type值与上传文件的实际内容类型不匹配,请求将会失败。我通过让文件为我填写该部分来修复它:

function send() {
    const formData = new FormData();
    const files = document.getElementById("file");
    formData.append("file", files.files[0]);
    const requestOptions = {
        headers: {
            "Content-Type": files.files[0].contentType, // This way, the Content-Type value in the header will always match the content type of the file
        },
        mode: "no-cors",
        method: "POST",
        files: files.files[0],
        body: formData,
    };
    console.log(requestOptions);

    fetch("http://localhost:5000/upload", requestOptions).then(
        (response) => {
            console.log(response.data);
        }
    );
}
© www.soinside.com 2019 - 2024. All rights reserved.