在项目中第一次遇到这个问题,当我在更新用【原创不易,请尊重版权】【访问 www.tangshuang.net 获取更多精彩内容】户头像的时候,选择使用put上传头像,然本文版权归作者所有,未经授权不得转载。原创内容,盗版必究。而服务端并不能通过$_FILES像我们以【转载请注明来源】【版权所有】唐霜 www.tangshuang.net前一样得到想要的结果。这是一个相当复杂的【原创不易,请尊重版权】【作者:唐霜】问题,我们这篇文章就来试图解决这个问题。
【访问 www.tangshuang.net 获取更多精彩内容】本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。restful post vs. put
【本文受版权保护】【原创不易,请尊重版权】【访问 www.tangshuang.net 获取更多精彩内容】如果我们希望严格保持restful风格,【本文受版权保护】【访问 www.tangshuang.net 获取更多精彩内容】那么一定要遵循post=add, put【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】=update的风格,在stackoverfollow【作者:唐霜】上已经有很多这样的讨论,所以,就不这里再著作权归作者所有,禁止商业用途转载。转载请注明出处:www.tangshuang.net讨论。但是restful不是规范,我们并【访问 www.tangshuang.net 获取更多精彩内容】【转载请注明来源】不一定非得严格按照这个规定去做,在适当的本文版权归作者所有,未经授权不得转载。【转载请注明来源】时候,其实我们确实可以选择使用post代原创内容,盗版必究。【原创不易,请尊重版权】替put.
【未经授权禁止转载】著作权归作者所有,禁止商业用途转载。【转载请注明来源】为什么仍然坚持put【版权所有】唐霜 www.tangshuang.net
【本文首发于唐霜的博客】【版权所有,侵权必究】【访问 www.tangshuang.net 获取更多精彩内容】【未经授权禁止转载】【原创内容,转载请注明出处】在PHP接受数据传递时,只有$_GET,转载请注明出处:www.tangshuang.net未经授权,禁止复制转载。 $_POST,而$_PUT和$_DEL转载请注明出处:www.tangshuang.net原创内容,盗版必究。ETE是没有的,当然,由于delete操【原创内容,转载请注明出处】【本文首发于唐霜的博客】作往往把要删除的资源直接在url中加以确转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net定。所以,现在其实最麻烦的,是put操作【版权所有,侵权必究】【访问 www.tangshuang.net 获取更多精彩内容】。
本文版权归作者所有,未经授权不得转载。【关注微信公众号:wwwtangshuangnet】原创内容,盗版必究。我们【原创不易,请尊重版权】有足够的理由使用put【本文首发于唐霜的博客】,因为我们在接受put信息时,采用的是p【版权所有,侵权必究】【版权所有,侵权必究】hp://input的形式,这也就是说,【访问 www.tangshuang.net 获取更多精彩内容】【版权所有】唐霜 www.tangshuang.net通过
【本文受版权保护】【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。原创内容,盗版必究。本文版权归作者所有,未经授权不得转载。file_get_contents('php://input')
可以获取传递内容的原始信息,以及二进制流原创内容,盗版必究。转载请注明出处:www.tangshuang.net,这使得传输和接受都是非常高效率的。我们【本文首发于唐霜的博客】【原创内容,转载请注明出处】甚至可以直接通过put传递文件的二进制流【本文首发于唐霜的博客】【本文首发于唐霜的博客】,在服务端保存这个二进制信息,就得到了原【版权所有】唐霜 www.tangshuang.net转载请注明出处:www.tangshuang.net始的文件。这个过程不会在服务器上产生临时【原创不易,请尊重版权】著作权归作者所有,禁止商业用途转载。文件,不会消耗更多的内存。
原创内容,盗版必究。【转载请注明来源】【版权所有】唐霜 www.tangshuang.net【本文首发于唐霜的博客】如何获取put信息原创内容,盗版必究。
本文作者:唐霜,转载请注明出处。【本文受版权保护】本文作者:唐霜,转载请注明出处。但是,随之而来的是,解析put信息成为让【未经授权禁止转载】未经授权,禁止复制转载。人非常烦恼的事,我们通过网上(官网)的一【本文首发于唐霜的博客】【转载请注明来源】些示例代码,发现也只能解决部分问题,比如【作者:唐霜】【版权所有】唐霜 www.tangshuang.net当我们通过发送put信息到服务端更新文章【未经授权禁止转载】【原创内容,转载请注明出处】信息时,由于文章信息不包含复杂信息,服务本文作者:唐霜,转载请注明出处。原创内容,盗版必究。端通过官方示例就可以得到对应的信息,而这未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。样的到的信息,和$_POST没有什么不同本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】。
【本文受版权保护】未经授权,禁止复制转载。【作者:唐霜】【版权所有,侵权必究】然而,如果发送的信息中如果含有文件,则情未经授权,禁止复制转载。本文作者:唐霜,转载请注明出处。况将会大不一样。
【作者:唐霜】本文作者:唐霜,转载请注明出处。【原创不易,请尊重版权】未经授权,禁止复制转载。在$_POST文件时,要求表单含有【访问 www.tangshuang.net 获取更多精彩内容】enctype=’multi【关注微信公众号:wwwtangshuangnet】【本文受版权保护】part/form-data’【原创内容,转载请注明出处】【作者:唐霜】;属性,而以往我们长长不去思考它的作用,现原创内容,盗版必究。【版权所有,侵权必究】在我们才知道,这其实时一中表单请求的加密转载请注明出处:www.tangshuang.net【关注微信公众号:wwwtangshuangnet】形式,当表单含有该属性,提交的内容中含有未经授权,禁止复制转载。【关注微信公众号:wwwtangshuangnet】文件时,服务器将会按照该规则进行解码,而【作者:唐霜】转载请注明出处:www.tangshuang.net解码的到的文件信息,将会以$_FILES【原创不易,请尊重版权】【未经授权禁止转载】返回。所以,当我们在使用post进行文件原创内容,盗版必究。【未经授权禁止转载】上传的时候,实际上,文件不能到$_POS【未经授权禁止转载】转载请注明出处:www.tangshuang.netT中去取,而是到$_FILES中。
原创内容,盗版必究。著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。put传输的是二进制信息流,因此不需要服本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。务端解码,自然也就不存在$_FILES的本文作者:唐霜,转载请注明出处。【版权所有】唐霜 www.tangshuang.net具体信息(为空)。这下我们就懵了,那上传未经授权,禁止复制转载。【作者:唐霜】的文件到哪里去了(我们知道$_FILES著作权归作者所有,禁止商业用途转载。【关注微信公众号:wwwtangshuangnet】中的文件保存在服务器临时目录中,需要我们本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。通过move_uploaded_file【访问 www.tangshuang.net 获取更多精彩内容】函数进行转移)?本文作者:唐霜,转载请注明出处。
未经授权,禁止复制转载。未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。【原创不易,请尊重版权】实际上,put的文件哪里都没有去,还在p本文作者:唐霜,转载请注明出处。【作者:唐霜】hp://input原始信息流中,我们要【本文受版权保护】原创内容,盗版必究。做的,是对php://input进行解码转载请注明出处:www.tangshuang.net【作者:唐霜】,得到我们想要的文件信息。
【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。【本文受版权保护】未经授权,禁止复制转载。【原创不易,请尊重版权】我们来看put得到的结果:【版权所有,侵权必究】
【版权所有,侵权必究】未经授权,禁止复制转载。【版权所有,侵权必究】【访问 www.tangshuang.net 获取更多精彩内容】转载请注明出处:www.tangshuang.netecho file_get_contents('php://input');
exit;
一般而言,我们可以得到两种结果,未经授权,禁止复制转载。
本文版权归作者所有,未经授权不得转载。【访问 www.tangshuang.net 获取更多精彩内容】【本文首发于唐霜的博客】【作者:唐霜】【未经授权禁止转载】一种:不包含文件的著作权归作者所有,禁止商业用途转载。
本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。原创内容,盗版必究。【转载请注明来源】【访问 www.tangshuang.net 获取更多精彩内容】这时我们长长得到的,是一串字符串,例如n转载请注明出处:www.tangshuang.net【本文受版权保护】ame=Jerry&age=18【关注微信公众号:wwwtangshuangnet】【版权所有,侵权必究】,我们在大部分PHP中如此去解析:
【本文受版权保护】未经授权,禁止复制转载。【版权所有】唐霜 www.tangshuang.net本文作者:唐霜,转载请注明出处。未经授权,禁止复制转载。parse_str(file_get_contents('php://input'), $_PUT);
另一种:包含文件的【本文受版权保护】
【转载请注明来源】【作者:唐霜】【转载请注明来源】这种情况是比较复杂的,我们会发现,php转载请注明出处:www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】://input是一个复杂的体系。
转载请注明出处:www.tangshuang.net【转载请注明来源】【未经授权禁止转载】------------------------------b2449e94a11c Content-Disposition: form-data; name="user_id" 3 ------------------------------b2449e94a11c Content-Disposition: form-data; name="post_id" 5 ------------------------------b2449e94a11c Content-Disposition: form-data; name="image"; filename="/tmp/current_file" Content-Type: application/octet-stream �����JFIF���������... a bunch of binary data
可以看到上面的结果中,用著作权归作者所有,禁止商业用途转载。------------------------------b2449e94a11c把整个内容分为了几个部分,其中第三个部分【访问 www.tangshuang.net 获取更多精彩内容】【版权所有,侵权必究】是一个文件。
经过观察,我们最终决定,用正则分析它,并本文版权归作者所有,未经授权不得转载。【版权所有】唐霜 www.tangshuang.net得到我们想要的结果,最后我参考一些网上的本文版权归作者所有,未经授权不得转载。未经授权,禁止复制转载。朋友给出的代码,总结了下面这个函数:
【访问 www.tangshuang.net 获取更多精彩内容】【原创不易,请尊重版权】【作者:唐霜】原创内容,盗版必究。【本文首发于唐霜的博客】/** * Parse raw HTTP request data
*
* Pass in $a_data as an array. This is done by reference to avoid copying
* the data around too much.
*
* Any files found in the request will be added by their field name to the
* $data['files'] array. * * https://www.tangshuang.net/?p=2294
*
* @param array Empty array to fill with data
* @return array Associative array of request data
*/
function parse_http_input_raw() {
$a_data = array();
// read incoming data
$input = file_get_contents('php://input');
// grab multipart boundary from content type header
preg_match('/boundary=(.*)$/', $_SERVER['CONTENT_TYPE'], $matches);
// content type is probably regular form-encoded
if (!count($matches)) {
// we expect regular puts to containt a query string containing data
parse_str(urldecode($input), $a_data);
return $a_data;
}
$boundary = $matches[1];
// split content by boundary and get rid of last -- element
$a_blocks = preg_split("/-+$boundary/", $input);
array_pop($a_blocks);
// loop data blocks
foreach ($a_blocks as $id => $block) {
if (empty($block)) continue;
// you'll have to var_dump $block to understand this and maybe replace or \r with a visibile char
// parse uploaded files
if (strpos($block, 'filename=') !== FALSE) {
// match "name", then everything after "stream" (optional) except for prepending newlines
preg_match("/name=\"([^\"]*)\".*filename=\"([^\"].*?)\".*Content-Type:\s+(.*?)[|\r|\r]+([^\r].*)?$/s", $block, $matches);
$a_data['files'][$matches[1]] = array(
'name' => $matches[1],
'filename' => $matches[2],
'type' => $matches[3],
'blob' => $matches[4]
);
}
// parse all other fields
else {
// match "name" and optional value in between newline sequences
preg_match('/name=\"([^\"]*)\"[|\r]+([^\r].*)?\r$/s', $block, $matches);
print_r($matches);
$a_data[$matches[1]] = $matches[2];
}
}
return $a_data;
}
所有的文件,被放在一个字段中提供使用:转载请注明出处:www.tangshuang.net
【版权所有】唐霜 www.tangshuang.net【未经授权禁止转载】未经授权,禁止复制转载。转载请注明出处:www.tangshuang.net【版权所有】唐霜 www.tangshuang.net$_PUT = parse_http_input_raw();
注意,文件的二进制流还在$_PUT中呢。【本文首发于唐霜的博客】【未经授权禁止转载】我们需要通过遍历$_PUT[‘【访问 www.tangshuang.net 获取更多精彩内容】著作权归作者所有,禁止商业用途转载。;files’]保存文件。
【本文首发于唐霜的博客】本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。【本文首发于唐霜的博客】【版权所有】唐霜 www.tangshuang.netjquery ajax如何去发起put请【转载请注明来源】著作权归作者所有,禁止商业用途转载。求和上传
转载请注明出处:www.tangshuang.net【本文首发于唐霜的博客】【版权所有,侵权必究】这个是最简单的了,可以看我之前写过的一些本文作者:唐霜,转载请注明出处。本文作者:唐霜,转载请注明出处。文章,非常详细,这里仅给出核心代码:
【未经授权禁止转载】【未经授权禁止转载】转载请注明出处:www.tangshuang.net$.ajax({
url: url,
type: 'PUT',
data: data,
success: function(result) {}
});
仅此而已。但是,当我们需要上传文件或图片原创内容,盗版必究。【未经授权禁止转载】的时候,就相对复杂一些,因为无论是POS未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】T或PUT,ajax都不会主动把表单中的【转载请注明来源】原创内容,盗版必究。文件流上传,而是只提交其他类型的数据。
【版权所有】唐霜 www.tangshuang.net【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。【版权所有】唐霜 www.tangshuang.net【转载请注明来源】我们需要借助未经授权,禁止复制转载。FormData()【转载请注明来源】来实现文件的ajax上传:【本文受版权保护】
【未经授权禁止转载】原创内容,盗版必究。【转载请注明来源】【作者:唐霜】转载请注明出处:www.tangshuang.net$('#form').on('submit',function(e) {
e.preventDefault();
var $form = $(this), $files = $form.find('input[type=file][name]'), data = new FormData();
$files.each(function() {
if ('files' in this && this.files.length > 0) {
data.append(this.name, this.files[0]);
}
});
// 省略了把非文件数据加入到data中
$.ajax({
url: 'your url',
type: 'PUT',
data: data,
contentType: false,
processData: false,
success: function(result) {}
});
});
可以看到,这个过程也很简单,并没有想象到著作权归作者所有,禁止商业用途转载。【作者:唐霜】那么复杂。通过new FormData(著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。)产生的对象,通过遍历form中的inp【版权所有】唐霜 www.tangshuang.net【版权所有,侵权必究】ut或其他数据对象,将结果逐个加入到da【版权所有,侵权必究】转载请注明出处:www.tangshuang.netta中。new FormData()有一著作权归作者所有,禁止商业用途转载。【本文受版权保护】个append方法,可以实现append著作权归作者所有,禁止商业用途转载。【原创不易,请尊重版权】(key,value),从而将你需要的数未经授权,禁止复制转载。【本文首发于唐霜的博客】据加入到data中,ajax提交到时候,【本文受版权保护】著作权归作者所有,禁止商业用途转载。data则是全部的有效数据(包括文件的二转载请注明出处:www.tangshuang.net转载请注明出处:www.tangshuang.net进制流)。
【作者:唐霜】未经授权,禁止复制转载。【访问 www.tangshuang.net 获取更多精彩内容】原创内容,盗版必究。【原创内容,转载请注明出处】(完)原创内容,盗版必究。
【作者:唐霜】未经授权,禁止复制转载。著作权归作者所有,禁止商业用途转载。未经授权,禁止复制转载。【原创内容,转载请注明出处】2016-03-26 13269 ajax



我目前也是碰到这个问题,使用PUT上传文件的话,使用file_get_contents(‘php://input’)会获取到html from-data格式的串,用正则匹配能解决文件比较小的情况,但是如果文件比较大的直接加载进内存会不会比较消耗资源,另外如果字符串中有’——————————xxxx’格式的文本会不会影响解析?\n能不能有比较好的方案,能够模仿PHP处理POST请求一样,把文件流存到临时文件,并通过$_FILES来保存?
这只是一种思路,具体的情况还是要根据你自己的编程情况来确定。\n你说文件比较大会不会加载内存消耗资源,这个真可能有,在post上传的时候,你可以看到浏览器有一个进度条,在服务器上的临时文件也是逐渐保存为一个和本地相同的文件的,也就是说这种上传有流式的效果,起码在文件上传完之后不会再占用资源,但是put是直接把整个文件的二进制内容上传上去,所以是一次性的,内存肯定会占用到你主动释放为止。\n字符串中有与分割信息相同的文本就要自己做处理,这个并不涉及本文的内容。\n至于你最后说模仿post结果,我觉得如果没有必要,直接用post代替效率更高,你用put本来不就是为了解决post的问题吗?现在你却返回来要模仿post,或许有点简单问题复杂化了。