这是一些已被窃听我一会儿..我的建筑,以在某些情况下接收文件REST的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);
当我再输出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
有谁知道如何正确地接收文件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' => '...'
));
===== =====解决方案
原来我做了一些错误的假设,主要是HTTP PUT将类似于HTTP POST。 正如你可以阅读下面,DaveRandom向我解释,HTTP PUT并不意味着对同一请求传输多个文件。
我现在已经搬到FORMDATA的从体内转移到URL查询字符串。 身体现在拥有一个单一的文件的内容。
欲了解更多信息,请阅读DaveRandom的答案。 这是史诗。
告诉你的数据不描绘一个有效的PUT请求主体(当然,它可以 ,但我很怀疑)。 它示出了一个multipart/form-data
请求体-通过一个HTML表单上传经由HTTP POST文件时使用的MIME类型。
PUT请求应完全恭维的GET请求的响应 - 他们给你在邮件正文中的文件内容,而不是其他。
基本上就是我要说的是,这是不是你的代码,即可获得,这是错误的文件,它是发出请求的代码-客户端代码不正确,不是你的代码显示在这里(虽然parse_str()
调用是一个毫无意义的运动)。
如果你能解释一下客户端是什么(浏览器,其他服务器上的脚本,等等),那么我可以帮你借此进一步。 正因为如此,为您描绘是POST请求主体的相应请求的方法,不能放。
让我们退一步从问题后面,并期待在一般的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工作在一个请求 - 响应架构 - 客户端发送的请求消息发送到服务器,服务器返回的响应消息给客户端。
请求消息包括一种方法,一个URI和任选的数目头。 请求方法是什么这个问题涉及到,所以这就是我将在这里最深度覆盖 - 但首先它确切地理解我们的意思,当我们谈论的请求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
请求的第一部分是字GET
-这是请求方法。 接下来的部分是通向我们所请求的文件 - 这是请求URI。 在该第一行的末尾是表示在使用中的协议版本的标识符。 在下面的行,你可以看到在MIME格式的标题,叫做Host
。 HTTP 1.1的任务,该Host:
报头被包括在每一个要求。 这是唯一的报头的这是真的。
请求URI被分成两个部分-一切问号左边?
是的路径 ,一切以它的右边是查询字符串 。
请求方法
RFC 2616(HTTP / 1.1)定义8种请求方法 。
OPTIONS
选项方法很少使用。 其目的是作为一个机制来确定什么样的功能服务器支持试图消耗服务的服务器可以提供之前。
关闭我的头顶,在相当普遍使用的唯一的地方,我能想到的地方,这是使用的是Microsoft Office直接通过HTTP从Internet Explorer中打开文档时 - 办公会发送一个OPTIONS请求到服务器,以确定它是否支持对特定URI的PUT方法,如果它确实会的方式,可以让用户保存自己的文档更改直接返回到远程服务器打开文档。 此功能是这些具体的Microsoft应用程序中紧密集成。
GET
这是远不是每天都使用的最常用的方法。 每次你在浏览器中加载一个常规文档时这将是一个GET请求。
GET方法请求服务器返回一个特定的文件。 应该发送给服务器的唯一数据是信息的服务器需要来确定应返回的文档。 这可以包括服务器可以使用来动态生成文件,其被在请求URI报头和/或查询字符串的形式发送信息。 虽然我们的主题 - Cookies是在请求的头部信息。
HEAD
这种方法是相同的GET方法,有一点不同 - 服务器将不会返回所请求的文件,如果将只返回将被包含在响应中的标头。 这是用于确定,例如是有用的,如果无需传送和处理整个文档中存在的特定文档。
POST
这是第二个最常用的方法,可以说是最复杂的。 POST方法请求几乎全部用来调用可能改变其状态的服务器上的一些动作。
POST请求,不像GET和HEAD,可以(且通常确实)包括在所述请求消息的主体中的一些数据。 该数据可以是任何格式,但最常见的是一个查询字符串(以相同的格式,因为它会出现在请求URI)或可以与文件附件沿通信键/值对的多部分消息。
许多HTML表单使用POST方法。 为了从浏览器上传文件,你需要使用POST方法的表单。
POST方法是使用RESTful API中的语义不兼容的,因为它不是幂等 。 也就是说,第二个相同的POST请求可能导致进一步改变到服务器的状态。 这违背REST的“无状态”约束。
PUT
这直接补充GET。 其中GET请求指示服务器应通过在响应身体的请求URI指定的位置返回该文件,PUT方法指示该服务器应在由请求URI指定的位置在请求体中的数据存储。
DELETE
这表明,服务器应在由请求URI所指示的位置销毁该文档。 当他们收到一个DELETE请求很少面向Internet的HTTP服务器实现将执行任何动作,相当明显的原因。
TRACE
这提供了应用层级别机制以允许客户端检查请求它已发送,因为它看起来通过它到达目标服务器的时间。 这是用于确定可在所述请求消息是具有客户机和目标服务器之间的任何代理服务器的作用主要是有用的。
CONNECT
HTTP 1.1的CONNECT方法保留了名字,但没有定义它的使用,甚至是它的目的。 有些代理服务器实现以来使用CONNECT方法,以促进HTTP隧道。
我已经使用PUT(GET和POST文件已足够满足我的需求)从来没有尝试过,但这个例子是从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);
?>
下面是我发现的最有用的解决方案。
$put = array(); parse_str(file_get_contents('php://input'), $put);
$put
将是一个数组,就像你在看惯了在$_POST
,除了现在你可以按照真正的REST HTTP协议。
使用POST并包括X-报头以指示(在此情况下PUT)的实际方法。 通常这是一个如何工作的防火墙不允许超过GET和POST等方法周围。 简单地声明PHP越野车(因为它拒绝处理多PUT有效载荷,这是越野车),并把它当作你会过时的/严厉的防火墙。
至于什么意见PUT手段相对于GET是正义的,意见。 该HTTP没有这样的要求。 它只是说“相当于” ..它是由设计师来确定什么“等同”的意思。 如果你的设计可以进行多文件上传PUT和产生“相当于”表示对同一资源的后续GET,这只是罚款和花花公子,无论在技术上和哲学,与HTTP规范。
只要按照它在说DOC :
<?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);
?>
这应该阅读整个文件是在PUT流并在本地保存它,那么你可以做你想做的事情是什么。