为什么 PHP curl 文件上传方法的结果与 HTML 表单文件上传不同


why results for php curl file upload method differs from html form file upload?

我正在做一些项目,突然我想出了这个问题。
请考虑使用一个名为 requestWithFile.htm 的文件,其中包含如下内容:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
</head>
<body>
  <form method="POST" action='http://127.0.0.1/pv.php' enctype="multipart/form-data">
    <input type="text" name="url" value="https://example.com/" /><br>
    <input type="file" name="myfile" /><br>
    <input type="submit">
  </form>
</body>
</html>

还有另一个在 PHP 中名为 requestWithFile.php 的文件,它执行相同的工作:

<?php
    $requesturl = "http://127.0.0.1/pv.php";
    $file = realpath('touploadfile.jpg');
    $ch = curl_init($requesturl);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, array(
    "url" => "https://example.com/",
    "myfile" => "@".$file
    ));
    echo curl_exec($ch);
    curl_close($ch);
?>

我在这两种情况下的帖子参数都是:
url => https://example.com/
myfile =>名为 touploadfile.jpg
的文件哪个touploadfile.jpg文件与 HTML 和 PHP 文件位于同一目录中。

pv.php文件包含用于显示我们发出的请求的代码。这些代码是:

<?php
    echo "The '$_POST :<br>'n'n";
    print_r($_POST); print "'n'n<br><br>";
    echo "The '$_GET :<br>'n'n";
    print_r($_GET); print "'n'n<br><br>";
    echo "The '$_REQUEST :<br>'n'n";
    print_r($_REQUEST); print "'n'n<br><br>";
    echo "The '$_FILES :<br>'n'n";
    print_r($_FILES); print "'n'n<br><br>";
    echo "The apache_request_headers: :<br>'n'n";
    print_r(apache_request_headers()); print "'n'n<br><br>";
?>

现在

如果我们使用第一个文件发出请求 requestWithFile.htm ,浏览器会回显:

The $_POST :
Array ( [url] => https://example.com/ )
The $_GET :
Array ( )
The $_REQUEST :
Array ( [url] => https://example.com/ )
The $_FILES :
Array ( [myfile] => Array ( [name] => touploadfile.jpg [type] => image/jpeg [tmp_name] => C:'xampp'tmp'phpB1B1.tmp [error] => 0 [size] => 69 ) )
The apache_request_headers: :
Array ( [Host] => 127.0.0.1 [User-Agent] => Mozilla/5.0 (Windows NT 6.1; WOW64; rv:45.0) Gecko/20100101 Firefox/45.0 [Accept] => text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8 [Accept-Language] => en-US,en;q=0.5 [Accept-Encoding] => gzip, deflate [Referer] => http://127.0.0.1/requestWithFile.htm [Connection] => keep-alive [Content-Type] => multipart/form-data; boundary=---------------------------1848618309200 [Content-Length] => 377 )

但是如果我们对requestWithFile.php文件发出相同的请求,结果会有所不同:

The $_POST :
Array ( [url] => https://example.com/ [myfile] => @C:'xampp'htdocs'touploadfile.jpg )
The $_GET :
Array ( )
The $_REQUEST :
Array ( [url] => https://example.com/ [myfile] => @C:'xampp'htdocs'touploadfile.jpg )
The $_FILES :
Array ( )
The apache_request_headers: :
Array ( [Host] => 127.0.0.1 [Accept] => */* [Content-Length] => 304 [Expect] => 100-continue [Content-Type] => multipart/form-data; boundary=------------------------122eddaaad7fe29d )

除了标头之间的差异(这是因为从 html 文件中的 Web 浏览器发送)之外,想到的问题是:
为什么 $_FILES 的值对于 php 文件是空的?
为什么两个相同请求的结果不同?
我自己想不通。

你使用的是哪个版本的 PHP?从 5.6 开始,文件上传的 @ 语法将被删除。请参阅新的:

https://wiki.php.net/rfc/curl-file-upload

所以基本上它应该看起来像这样:

curl_setopt($ch, CURLOPT_POSTFIELDS, array(
  "url" => "https://example.com/",
  "myfile" => curl_file_create($file) // alias of new CURLFile($path)
));