通过FormData API和AJAX上传图像不起作用($_FILES始终为空)

时间:2020-05-22 作者:DevelJoe

当我尝试执行标题中提到的操作时,我的请求都能正常工作(nonce-check通过,服务器响应200已接收,服务器脚本也能正常工作)。我的问题是,我无法访问服务器端脚本上上载的图像文件$_文件始终为空。虽然已经有很多关于堆栈溢出的帖子,但他们的解决方案都不适合我。

我的HTML(请注意,我不使用表单标记,但应该不会有问题):

<input type=\'file\' name=\'imageupload\' id=\'image-for-upload\'>
<button onclick="testAjax()">Launch AJAX Request</button>
我的JavaScript:

function testAjax() {
  let uploadContainer = document.getElementById(\'image-for-upload\');
  let file = uploadContainer.files[0];
  let data = new FormData();
  data.append("image",file);
  data.append("_ajax_nonce",test_ajax.nonce);
  data.append("action","test_ajax");
  let xhttp = new XMLHttpRequest();
  xhttp.onreadystatechange = function() {
    if (this.readyState == 4 && this.status == 200) {
      alert(this.responseText);
    } else {
      console.log(this.status);
    }
  };
  xhttp.open(\'POST\', ajaxurl, true);
  //xhttp.setRequestHeader("Content-type","multipart/form-data");
  xhttp.send(data);
}
注意,我注释掉了setRequestHeader行,因为使用它,服务器返回一个客户机错误(404),并用“0”回答。根据我的发现,这意味着服务器不理解动作挂钩。移除时setRequestHeader, 事情进展顺利(除了这个问题)。然而,在检查已发送请求的HTTP请求头时,我实际上可以看到

Content-type: multipart/form-data; boundary=...
。。。所以对于那个头球,无论如何都应该没问题。

我的服务器脚本:

<?php
// Ajax script used for testing purposes
check_ajax_referer(\'ajax-test\');
if (empty($_FILES[\'imageupload\'])) {
  echo \'The file is not recognized!\';
} else {
  //echo \'it is not working!\';
  echo \'It is working!\';
}
?>
无论我做什么,我总是得到一个200服务器响应,回应“文件无法识别!”。帮助(请坚持使用vanilla js,我不想在jQuery中编写代码)。

P、 S:当我更准确地观察我的HTTP请求和ajax请求时,我可以看到以下(第一)部分:

Content-Disposition: form-data; name="image"; filename="myImage.jpg"
Content-Type: image/jpeg
我得到了一个非常长的看起来很奇怪的红色填充点字符串和随机类型的字符,所以可能有些编码工作不正常?或者,对于通过表单数据发送图像的请求机构来说,这是常见的吗?

还有,当我使用

var_dump($_POST);
。。。作为服务器端脚本中的服务器响应,我得到一个带有键的关联数组

[image] => undefined
[_ajax_nonce] => nonce
[action] => test_ajax
。。当我在没有在浏览器中上载文件的情况下发出请求时。

当我将文件上载到浏览器中,然后触发请求时,我会得到一个关联数组,其中没有[image] => undefined 元素,只有后两个,所以当我上传一个时似乎没有考虑我的图像。。。?

1 个回复
最合适的回答,由SO网友:DevelJoe 整理而成

好吧,过了几天几小时就明白了;我的错误是,我试图访问上载的图像,其值为name 属性,使用:

$_FILES[\'imageupload\']
显然,当您使用formData API上载文件时,用于访问文件的密钥不是name 您的属性input 标记不再用于上载,但它会被您在相应元素的formdata中指定的键覆盖。简单地说,包括:

<input type="file" name="imageupload" id="myElement"/>
在HTML中(name 属性实际上已过时,您甚至不需要指定它),并且:

myFormData.append(\'image\',file);
在JavaScript中,您实际上可以通过以下方式在服务器端访问PHP中的文件:

$_FILES[\'image\']
而不是:

$_FILES[\'imageupload\']
还有别的。如果服务器端的脚本是php,则应始终以JavaScript的方式指定表单数据的文件:

data.append(\'image[]\', file);
而不是

data.append(\'image\',file);
正如我在上面写的那样。然而,这并没有改变您在PHP中访问文件的方式,只需使用我上面解释的方式即可。