【问题标题】:Upload files to Flask server via xhr通过 xhr 将文件上传到 Flask 服务器
【发布时间】:2021-11-07 23:52:33
【问题描述】:

我正在尝试使用烧瓶和表单创建文件上传,但它不太有效。我根本无法弄清楚问题出在哪里。我尝试了多个教程并查看了许多堆栈溢出线程无济于事。

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。为什么图片似乎没有包含在请求中?

【问题讨论】:

    标签: javascript python flask file-upload xmlhttprequest


    【解决方案1】:

    问题是我试图自己处理设置请求标头。只需删除这一行:xhr.setRequestHeader("Content-Type", "multipart/form-data") 就为我解决了问题。

    故事的寓意是让 XMLHttpRequest 为您处理标题,它知道在提交表单数据的情况下它已经在做什么了。

    【讨论】:

      【解决方案2】:

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

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

      然后在 BE 上使用:

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

      【讨论】:

      • 您好,感谢您的回复!不幸的是,它似乎不起作用,但它让我向前迈出了一步。使用 request.files['file'] 使得无论我选择上传什么,在浏览器中发出的发布请求都是 16kb,而不是请求大小小于 1kb,并且在 python 方面,它会在request.files 行。这种行为发生在我们没有修改 js
      • 嗯,好的,明白了,你自己解决它,就像我在另一个答案中看到的那样,你也可以将你的答案标记为正在解决的问题。 XMLHTTPRequest 是一个棘手的问题,现在推荐的标准是使用 Fetch API (developer.mozilla.org/en-US/docs/Web/API/Fetch_API),它是一种更灵活、更强大的请求处理方式
      • 感谢您告诉我!将来我一定会尝试过渡到使用 fetch 。老实说,我认为 fetch 要么是 node.js 的东西,要么是某种外部库,所以我什至没有考虑尝试使用它
      猜你喜欢
      • 1970-01-01
      • 2020-09-22
      • 1970-01-01
      • 2016-07-07
      • 2016-10-22
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2014-08-26
      相关资源
      最近更新 更多