使用Curl进行文件上传的PUT请求到PHP

5
我正在尝试使用HTTP PUT上传文件。
阅读了一些资料后,似乎$_FILES数组仅适用于POST和multipart/form-data。 而对于PUT,我需要手动读取php://input来获取数据。 两种方法都不起作用。
我尝试了以下选项,并希望您能提供任何建议:
curl --upload avatar.jpg http://api.test.com/user/dsadasdsa
curl -X PUT -F "filedata=@avatar.jpg" http://api.test.com/user/dsadasdsa

我的PHP文件想要打印出这个内容,但是返回了一个空字符串:

echo file_get_contents("php://input");

我开始认为这可能是Nginx缺少PUT DELETE支持的问题,并安装了nginx-extras,同时在我的Nginx配置中添加了以下内容,但不幸的是,这也没有帮助解决问题。
root /var/www/;

dav_methods PUT DELETE MKCOL COPY MOVE;

create_full_put_path on;
dav_access group:rw all:r;

参考链接 http://php.net/manual/zh/features.file-upload.put-method.php - Gordon
@Gordon - 谢谢。我知道那个页面,但它只告诉我在PHP端该怎么做(我已经在做了)。并没有真正告诉我在curl方面我做错了什么。 - Shai Mishali
此外,尝试从手册中运行完全相同的代码只会创建一个空文件。因此,我非常确定我的CURL请求是错误的。 - Shai Mishali
请尝试访问http://stackoverflow.com/questions/15106849/curl-php-uploading-files-with-put-request-how-do-i-process-this/15106995#15106995。 - Gordon
我也来自那里... 我开始觉得错误可能是由于Nginx需要特定的安装才能支持PUT/DELETE,我会尝试一下。感谢您的帮助! - Shai Mishali
增加了一些关于 Nginx 方面的信息,但我仍然卡住了... - Shai Mishali
6个回答

3

我有一些调试的想法。

使用var_dump(file_get_contents('php://input'));而不是echo。根据参考文献

此函数可能返回布尔值FALSE,但也可能返回计算为FALSE的非布尔值。请阅读布尔值一节以获取更多信息。请使用===运算符测试此函数的返回值。

如果输出为bool(false),则表示存在问题,导致无法读取php://input - 最可能是PHP问题。 如果输出为string(0) "",则php://input中什么都没有(或不再有),这使得nginx问题更加可能。

此外,根据php://参考文献,您不能将php://inputenctype="multipart/form-data"一起使用。您确定您没有使用那个吗? 如果这更熟悉,请尝试HTML文件。

您还可以检查错误日志,默认为/var/log/nginx/error.log。此外,请检查HTTP响应代码。 它是200吗? 如果不是,它是否是一个有用的代码?


很遗憾我还没有测试过这个,但是你的答案到目前为止似乎是最详尽的。谢谢! - Shai Mishali
@ShaiMishali,请告诉我您是否进行了测试。感谢您的推荐:) - user1544337

2

你所使用的选项-F 会使curl以Content-Type multipart/form-data(详见man curl)的形式POST数据。

你可以使用--data-binary选项,例如:

curl -X PUT --data-binary "@avatar.jpg" http://api.test.com/user/dsadasdsa

-d选项仅适用于文本,可能会损坏您的数据。

在我的测试中,以下命令给出相同的结果。

curl --upload "avatar.jpg" http://api.test.com/user/dsadasdsa

这是我的服务器

<?php
echo "request method : " . $_SERVER['REQUEST_METHOD'] . "\n";
echo "dump files ";
var_dump($_FILES);

$putdata = fopen("php://input", "r");
while ($data = fread($putdata, 1024)) {
      echo $data . "\n";
}
?>

1
"Nginx支持所有的HTTP动词(put,delete,options等),因此您不需要在nginx中进行任何特殊设置。下面的内容可以正常工作(我使用php5.4服务器轻松测试):将这个名为put.php的简单测试php脚本添加进去。"
$putdata = fopen("php://input", "r");
while ($data = fread($putdata, 1024)) {
      echo $data . "\n";
}

从与put.php相同的文件夹启动php服务器:

php -S localhost:5000

发出一个 PUT curl 请求:
curl -d "@/path/to/put.php" -X PUT http://localhost:5000/put.php

这将打印put.php文件的内容。
[更新]
如果您想使用php向restful api网站发送curl请求,我建议使用Guzzle,它可以让您不必记住所有curl选项。

0

两种方法都不起作用

我从未尝试过使用PHP实现DAV,但我可以向您保证,即使在nginx上,使用文件上传的POST也可以正常工作。

curl --upload avatar.jpg http://api.test.com/user/dsadasdsa

我本来期望这个命令可以工作 - 您的日志显示了什么?您尝试过使用“--trace”吗?

curl -X PUT -F "filedata=@avatar.jpg" http://api.test.com/user/dsadasdsa

使用curl的-F标志意味着将文件作为POST变量上传,使用multipart/form-data编码 - 这在PUT请求中没有任何意义。


0
你是否通过在nginx后面放置另一种Web应用程序并测试其是否能处理PUT上传来排除了PHP作为问题的原因?一个非常简短的Python Flask应用程序将让您测试其他语言中的PUT上传。

0

如果您正在尝试创建一个PUT请求到服务器,但无法从php包装器中读取,请确保:

  1. 您拥有正确的PUT请求。包括头文件和其他内容(使用PHP和CURL进行PUT请求)

  2. 您的服务器接受PUT请求。

  3. 您的php文件可以先读取简单的PUT请求(不包括上传部分)

您还可以查看php://input中指示的“注意事项”(http://php.net/manual/en/wrappers.php.php)。除此之外,这可能是服务器上的问题。


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接