PHP文件上传PUT请求改变文件,而POST不改变文件


PHP file upload PUT request alters file, while POST does not

我有以下代码,只是为了从PUT请求或POST请求中获取文件并将其复制到服务器。

if ($_SERVER['REQUEST_METHOD']=='PUT') {
    $putdata = fopen("php://input","r");
    $fp = fopen("myputfile.ext","w");
    while ($data = fread($putdata, 1024))
            fwrite($fp, $data);
    fclose($fp);
    fclose($putdata);
} else {
    move_uploaded_file($_FILES['package']['tmp_name'], "mypostfile.ext");
}

因此对于POST请求,文件(在本例中是zip文件)是不变的。使用PUT请求,文件将被更改。

[root@vm-centos6-010 put]# diff myputfile.ext ../post/mypostfile.ext 
Binary files myputfile.ext and ../post/mypostfile.ext differ

它是一个zip文件,根据unzip,在开始处额外添加了165字节。它仍然成功解压缩,但是POST'ed文件中没有出现警告消息。我真正知道的唯一线索是文件大小相差211字节。

我已经梳理了php文档和十几篇文章,但我不明白为什么这两种方法会不同。

见解吗?

谢谢。

^M为windows行结束字符CR LF (0x0D 0x0A'r'n)。

打开流$putdata = fopen("php://input","r");

首先发送报头,然后发送文件(报头和正文由'r'n'r'n分隔)。

我不知道你的设置是哪个部分导致错误,但你应该检查这些字符,如果它们存在,你知道文件从'r'n'r'n之后开始

你的请求有问题。您尝试PUT请求的方式是错误的。

如何使用PHP通过HTTP PUT接收文件

这直接补充了GET。其中GET请求指示方法指定的位置返回文档请求URI中的响应体,则PUT方法指示服务器应该将数据存储在请求体中的位置

这意味着,您可能不会在单个PUT请求中包含多部分请求。必须有单一的内容类型。(Multipart用:------WebKitFormBoundaryhPjNpS0gBhbCC8aR表示)

在POST请求中,允许有多个部分(想想:enctype='multipart/form-data')。

带文件的put请求不能包含任何其他内容。这意味着,如果你想把一个文件+变量,变量需要追加到URI,但不像POST,在正文中。

更新可能的解决方案(我知道这是一个肮脏的解决方案,请不要怪我....):

while ($data = fread($putdata, 1024)) {
    if (strpos($data, ''r'n'r'n') !== false) {
        $data = explode("'r'n'r'n", $data);  // seperate multipart header from body
        $data = $data[1];                    // assign body to $data
    } elseif(strpos($data, ''r'n-' !== false) {
        $data = explode("'r'n-", $data);  // seperate footer from body
        $data = $data[0];                    // assign body to $data
    }
    fwrite($fp, $data);
}

听起来好像有东西被添加到输出中。在文本编辑器中打开ZIP文件,检查服务器/PHP生成的警告消息/无意输出的内容。