Mau*_*ice 30 php http file put
这一直困扰着我一段时间......我正在构建一个RESTful API,在某些情况下必须接收文件.
使用时HTTP POST,我们可以阅读data from $_POST和files from $_FILES.
使用时HTTP GET,我们可以阅读data from $_GET和files from $_FILES.
但是,在使用时HTTP PUT,AFAIK读取数据的唯一方法就是使用了php://input stream.
一切都很好,直到我想通过HTTP PUT发送文件.现在php://输入流不再按预期工作了,因为它也有一个文件.
这是我目前如何读取PUT请求的数据:
(只要没有发布文件,它就能很好用)
$handle = fopen('php://input', 'r');
$rawData = '';
while ($chunk = fread($handle, 1024)) {
$rawData .= $chunk;
}
parse_str($rawData, $data);
Run Code Online (Sandbox Code Playgroud)
当我输出rawData时,它显示
-----ZENDHTTPCLIENT-44cf242ea3173cfa0b97f80c68608c4c
Content-Disposition: form-data; name="image_01"; filename="lorem-ipsum.png"
Content-Type: image/png; charset=binary
?PNG
???...etc etc...
???,
-----ZENDHTTPCLIENT-8e4c65a6678d3ef287a07eb1da6a5380
Content-Disposition: form-data; name="testkey"
testvalue
-----ZENDHTTPCLIENT-8e4c65a6678d3ef287a07eb1da6a5380
Content-Disposition: form-data; name="otherkey"
othervalue
Run Code Online (Sandbox Code Playgroud)
有谁知道如何通过HTTP PUT正确接收文件,或者如何解析php://输入流中的文件?
=====更新#1 =====
我只尝试过上面的方法,不知道我能做些什么.
我使用这种方法没有错误,除了我没有得到所发布的数据和文件的预期结果.
=====更新#2 =====
我正在使用Zend_Http_Client发送此测试请求,如下所示:(到目前为止Zend_Http_Client没有任何问题)
$client = new Zend_Http_Client();
$client->setConfig(array(
'strict' => false,
'maxredirects' => 0,
'timeout' => 30)
);
$client->setUri( 'http://...' );
$client->setMethod(Zend_Http_Client::PUT);
$client->setFileUpload( dirname(__FILE__) . '/files/lorem-ipsum.png', 'image_01');
$client->setParameterPost(array('testkey' => 'testvalue', 'otherkey' => 'othervalue');
$client->setHeaders(array(
'api_key' => '...',
'identity' => '...',
'credential' => '...'
));
Run Code Online (Sandbox Code Playgroud)
=====解决方案=====
结果我做了一些错误的假设,主要是HTTP PUT类似于HTTP POST.如下所示,DaveRandom向我解释说,HTTP PUT不适用于在同一请求中传输多个文件.
我现在已经将formdata从body转移到url querystring.正文现在保存单个文件的内容.
有关更多信息,请阅读DaveRandom的回答.这是史诗.
Dav*_*dom 42
您显示的数据并未描述有效的PUT请求正文(嗯,它可以,但我非常怀疑).它显示的是一个multipart/form-data请求体 - 通过HTTP表单通过HTTP表单上传文件时使用的MIME类型.
PUT请求应该完全补充对GET请求的响应 - 它们会向您发送消息体中的文件内容,而不是其他内容.
基本上我所说的是,接收错误的文件不是你的代码,它是发出请求的代码 - 客户端代码不正确,而不是你在这里显示的代码(虽然parse_str()调用是没有意义的行使).
如果您解释客户端是什么(浏览器,其他服务器上的脚本等),那么我可以帮助您进一步.实际上,您描述的请求主体的适当请求方法是POST,而不是PUT.
让我们从问题中退后一步,看看一般的HTTP协议 - 特别是客户端请求方 - 希望这将有助于您了解所有这些应该如何工作.首先,有一点历史(如果你对此不感兴趣,请随意跳过本节).
历史
HTTP最初被设计为从远程服务器检索HTML文档的机制.起初它只有效地支持GET方法,客户端会按名称请求文档,服务器会将其返回给客户端.HTTP的第一个公共规范,标记为HTTP 0.9,出现在1991年 - 如果您有兴趣,可以在这里阅读.
HTTP 1.0规范(1996年使用RFC 1945形式化)大大扩展了协议的功能,添加了HEAD和POST方法.它没有向后兼容HTTP 0.9,因为响应格式发生了变化 - 添加了响应代码,以及以MIME格式标题的形式包含返回文档的元数据的能力 - 键/值数据对.HTTP 1.0还从HTML中抽象出协议,允许以其他格式传输文件和数据.
HTTP 1.1是目前几乎全部使用的协议形式,它建立在HTTP 1.0之上,旨在向后兼容HTTP 1.0实现.它在1999年通过RFC 2616标准化.如果您是使用HTTP的开发人员,请了解此文档 - 这是您的圣经.充分理解它会比没有这样做的同行更具优势.
已经达到了目的
HTTP在请求 - 响应体系结构上工作 - 客户端向服务器发送请求消息,服务器向客户端返回响应消息.
请求消息包括METHOD,URI和可选的多个HEADERS.请求METHOD是这个问题所涉及的,所以我将在这里深入讨论 - 但首先,在我们讨论请求URI时,确切了解我们的意思是很重要的.
URI是我们请求的资源的服务器上的位置.通常,它由路径组件和可选的查询字符串组成.在某些情况下,也可能存在其他组件,但为了简单起见,我们暂时忽略它们.
我们假设您输入http://server.domain.tld/path/to/document.ext?key=value浏览器的地址栏.浏览器会解除此字符串,并确定它需要连接到HTTP服务器server.domain.tld,并在此处请求文档/path/to/document.ext?key=value.
生成的HTTP 1.1请求将(至少)看起来像这样:
GET /path/to/document.ext?key=value HTTP/1.1
Host: server.domain.tld
Run Code Online (Sandbox Code Playgroud)
请求的第一部分是单词GET- 这是请求METHOD.下一部分是我们请求的文件的路径 - 这是请求URI.在第一行的末尾是指示正在使用的协议版本的标识符.在以下行中,您可以看到MIME格式的标题,称为Host.HTTP 1.1要求Host:每个请求都包含标头.这是唯一的标题.
请求URI被分成两个部分-一切问号左边?是路径,一切以它的右边是查询字符串.
请求方法
RFC 2616(HTTP/1.1)定义了8种请求方法.
OPTIONS
OPTIONS方法很少使用.它旨在作为一种机制,用于在尝试使用服务器可能提供的服务之前确定服务器支持哪种功能.
在我的头脑中,我能想到使用它的唯一常见用法是在Microsoft Office中直接通过HTTP从Internet Explorer打开文档 - Office会向服务器发送OPTIONS请求以确定是否支持特定URI的PUT方法,如果支持,它将以允许用户将对文档的更改直接保存回远程服务器的方式打开文档.此功能紧密集成在这些特定的Microsoft应用程序中.
GET
这是迄今为止每天使用中最常用的方法.每次在Web浏览器中加载常规文档时,都将是GET请求.
GET方法请求服务器返回特定文档.应该传输到服务器的唯一数据是服务器确定应返回哪个文档所需的信息.这可以包括服务器可以用来动态生成文档的信息,该信息以请求URI中的头和/或查询字符串的形式发送.我们讨论的主题是 - 在请求标头中发送Cookie.
HEAD
此方法与GET方法相同,但有一点不同 - 服务器将不返回请求的文档,如果只返回将包含在响应中的标头.例如,这对于确定特定文档是否存在而不必传输和处理整个文档是有用的.
POST
这是第二种最常用的方法,可以说是最复杂的方法.POST方法请求几乎专门用于调用服务器上可能更改其状态的某些操作.
与GET和HEAD不同,POST请求可以(并且通常确实)在请求消息的主体中包含一些数据.此数据可以是任何格式,但最常见的是查询字符串(格式与请求URI中显示的格式相同)或多部分消息,可以与文件附件一起传递键/值对.
许多HTML表单使用POST方法.要从浏览器上传文件,您需要为表单使用POST方法.
POST方法在语义上与RESTful API不兼容,因为它不是幂等的.也就是说,第二个相同的POST请求可能导致对服务器状态的进一步改变.这与REST的"无状态"约束相矛盾.
PUT
这直接补充了GET.如果GET请求指示服务器应在响应主体中的请求URI指定的位置返回文档,则PUT方法指示服务器应将数据存储在请求URI指定的位置的请求主体中.
DELETE
这表明服务器应该在请求URI指示的位置销毁文档.很少有面向互联网的HTTP服务器实现在收到DELETE请求时会执行任何操作,原因相当明显.
TRACE
这提供了一种应用程序层级机制,允许客户端在到达目标服务器时检查它发送的请求.这对于确定客户端和目标服务器之间的任何代理服务器可能对请求消息产生的影响非常有用.
CONNECT
HTTP 1.1保留CONNECT方法的名称,但不定义其用法,甚至不限定其用途.从那时起,一些代理服务器实现使用CONNECT方法来促进HTTP隧道.
我从来没有尝试过使用PUT(GET POST和FILES足以满足我的需求),但这个例子来自php文档,所以它可以帮到你(http://php.net/manual/en/features.file-upload.把-method.php):
<?php
/* PUT data comes in on the stdin stream */
$putdata = fopen("php://input", "r");
/* Open a file for writing */
$fp = fopen("myputfile.ext", "w");
/* Read the data 1 KB at a time
and write to the file */
while ($data = fread($putdata, 1024))
fwrite($fp, $data);
/* Close the streams */
fclose($fp);
fclose($putdata);
?>
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
30414 次 |
| 最近记录: |