通过xhr上传文件到Flask服务器

Upload files to Flask server via xhr

我正在尝试使用 Flask 和表单创建文件上传,但效果不佳。我完全不知道问题出在哪里。我尝试了多个教程并查看了许多堆栈溢出线程都无济于事。

Flask 似乎根本没有收到任何表单数据,我不明白为什么。这是我的 python 上传端点代码:

@app.route("/upload", methods=["post"])
def upload_endpoint():
    # Just prints ImmutableMultiDict([]) twice
    print(request.form)
    print(request.files)
    return "Success", 200

这是我上传过程相关的js:

// Creates and returns an input element with all needed tags and event listeners
function createInput() {
    const input = document.createElement("input")
    input.setAttribute("type", "file")
    input.setAttribute("multiple", "true")
    input.setAttribute("name", "file")

    input.addEventListener("change", () => {
        submitInput(input)
    }, false)

    return input
}

// Takes an input tag, puts it in a form, and submits it via xhr
function submitInput(input) {
    const form = document.createElement("form")
    form.appendChild(input)

    const xhr = new XMLHttpRequest()
    xhr.open("POST", "/upload")

    // Calculates and logs upload progress
    xhr.upload.addEventListener("progress", (e) => {
        const percent = e.lengthComputable ? (e.loaded / e.total) * 100 : 0
        console.log(percent.toFixed(2))
    })

    xhr.setRequestHeader("Content-Type", "multipart/form-data")
    xhr.send(new FormData(form))
}

// Handles for when element is clicked. .click() is used to create the popup dialogue for selecting a fike
centerDrop.addEventListener("click", () => {
    const input = createInput()
    input.click()
    return false
}, false)

// Handles for when a file is dropped into the browser
dropArea.addEventListener("drop", (e) => {
    const input = createInput()
    input.files = e.dataTransfer.files
    submitInput(input)
}, false)

我一直在用 200kb 的图像测试上传功能,但是根据浏览器中的开发控制台,正在创建的请求的大小小于 1kb。为什么图像似乎没有包含在请求中?

与其以编程方式将整个输入添加到表单中,不如尝试仅添加其文件:

function submitInput(input) {
    ...
    form.append("file", input.files) // Instead of form.appendChild(input)
    ...
}

然后在 BE 上访问它:

print("files:", request.files['file'])

问题是我试图自己处理设置请求 headers。只需删除这一行:xhr.setRequestHeader("Content-Type", "multipart/form-data") 对我有用。

故事的寓意是让 XMLHttpRequest 为您处理 headers,在提交表单数据的情况下,它知道自己在做什么。