【问题标题】:How to mimic file uploads using XMLHttpRequest?如何使用 XMLHttpRequest 模拟文件上传?
【发布时间】:2020-05-08 14:03:02
【问题描述】:

PHP 收到一个上传文件的 post 请求。 print_r($_FILES); 输出以下内容:

Array
(
    [resource] => Array
        (
            [name] => test.log
            [type] => application/octet-stream
            [tmp_name] => /tmp/php2O7WQy
            [error] => 0
            [size] => 6136
        )
)

使用 PHP,我将各种请求数据作为字符串回显到页面。

我还在页面中添加了以下 JavaScript:

var uri = document.getElementById("uri").textContent;
var body = document.getElementById("body").textContent;
var files = document.getElementById("files").textContent;
var headers = JSON.parse(document.getElementById("headers").textContent);
var contentType = document.getElementById("contentType").textContent;

var xhttp = new XMLHttpRequest();
xhttp.open(method, uri);
for (var name in headers) {
    for (var i = 0; i < headers[name].length; i++) {
        console.log(name, headers[name][i]);
        xhttp.setRequestHeader(name, headers[name][i]);
    }
}
if(contentType) xhttp.setRequestHeader("Content-Type", contentType);
var parsedFiles=JSON.parse(files);
if(typeof parsedFiles.resource !=='undefined') {
    console.log(JSON.stringify(parsedFiles)); //{"resource":{"name":"test.log","type":"application/octet-stream","tmp_name":"/tmp/php2O7WQy","error":0,"size":6136}}
    var formData = new FormData();
    formData.append('resource', parsedFiles.resource.tmp_name, parsedFiles.resource.name);
    xhttp.send(formData);
}
else {
    xhttp.send(body);
}
xhttp.onreadystatechange = function() {
    if (this.readyState == 4) {
        document.getElementById('output').innerHTML=xhttp.responseText;
    }
};

但是,当服务器收到 XMLHttpRequest 时,$_FILES 为空。

如果我知道文件 tmp_name,如何生成 XMLHttpRequest 以便服务器使用该文件?作为替代方案,我应该将文件保存为页面上的 blob 字符串并发送吗?

【问题讨论】:

  • 只要在 SO 上搜索。你不是第一个想用XMLHttpRequest提交文件的人

标签: javascript php xmlhttprequest


【解决方案1】:

如果您只想使用 XHR 上传文件,请尝试以下代码。

var data = new FormData();
data.append("file", fileInput.files[0], "path/to/your/file");

var xhr = new XMLHttpRequest();
xhr.withCredentials = true;

xhr.addEventListener("readystatechange", function() {
  if(this.readyState === 4) {
    console.log(this.responseText);
  }
});

xhr.open("POST", "url");
xhr.send(data);

【讨论】:

  • 我将在我的答案中发布您的代码的替代方案,并在其中稍作调整,以便提出问题的人有两种选择。
  • 当然,那对我也很好。
  • 谢谢 Sahil,我想我已经很接近了。正如我原来的帖子所见,我尝试了formData.append('resource', parsedFiles.resource.tmp_name, parsedFiles.resource.name);。看起来我误读了developer.mozilla.org/en-US/docs/Web/API/FormData/append 并错误地交换了第二个和第三个参数。
  • 它发生了,很高兴知道它有帮助。顺便说一句,@syedmh 正在发布不同的方法,请随意尝试两种方法。
  • 还是什么都没有。刚看到_test.php:58 Uncaught TypeError: Failed to execute 'append' on 'FormData': parameter 2 is not of type 'Blob'.。我看到你们俩都用过fileInput.files[0]。那必须是实际文件,而不是通用文件名。看起来我需要将文件保存为客户端上的字符串。认为我在正确的轨道上。感谢您的帮助。
【解决方案2】:

除了 Sahil Paudel 的回答之外,这里有一种稍微不同的方式来编写代码以使用更现代的标准:

让我们以此为例:

<form>
    <input type='file'>
    <button type="submit">Submit</button>
</form>

要提交此文件,您可以使用以下内容:

document.querySelector(form button[type="submit"]).addEventListener('click', e => {
    
    e.preventDefault();

    let form, data, xhr;
    form = this.parentElement;
    data = new FormData(form);
    xhr = new XMLHttpRequest();
    
    xhr.open('POST', /*url*/);

    xhr.onload = function() {
        if(this.status === 200) {
            // do something with a positive response
        }
    }

    xhr.onerror = function() {
        // handle errors
    }

    xhr.send(data);

});

这是我用来上传文件的一种方法,它会自动将您的文件附加到您的 XMLHttpRequest 并在 PHP 中的$_FILES 中提供给您。

【讨论】:

    猜你喜欢
    • 2011-08-21
    • 2013-06-12
    • 2021-03-05
    • 2012-05-15
    • 2011-09-06
    相关资源
    最近更新 更多