PHP curl 关于 put 和 post 使用上的一个小问题

2019-11-24 04:50:02 +08:00
 pinews
ucloud 对象存储在上传单文件,api 和 sdk 给我造成了一点困扰,api 说了 HTTP 方法是 put,但 phpsdk 用的 postfields,这不是 post 吗?参考网页和腾讯的 sdk 都是乖乖用的 UPLOAD READATA。
对于我来说奇怪的地方在于,ucloud 用的 file_get_contents,而后面用的 fopen,如果把 fopen 改成 file_get_contents (相当于 fopen,fread,fclose 的集合)就会报错,说必须用 file_handle。
腾讯的也可以按照 ucloud 的做法用,网易会报错认证失败。

之所以这样是因为,put 和 post 最大区别在于 post 可以提交多个字段的内容,多个字段内容用&或者随机字符边界分割。
如果提交的只有一个内容,格式应该是没区别的,所以在对象存储上传单文件的时候用 postfields,服务器收到的内容是一样的,之所以 ucloud 和腾讯可以通过,应该是忽略了收到方法为 post,而是直接固定用了 put,而网易按收到的方法校验,file_get_contents 显然比 fopen 这个方法好用啊,fopen 还要接着写个 fclose,或许 ucloud 在这里偷了个懒。
curl 并不是靠传来的方法作为使用方法,而是用实际判断真实方法,用 upload 就一定是 put,用 postfields 就会是 post。

我奇怪的就是为什么 READATA 一定要是个资源句柄,而不是文件的真实内容呢?

c#用的也是 openread 方法,c#不太懂,我看了 curl 的源码也看不懂,不知道 READATA 和 postfields 最后在哪产生了分别。
2932 次点击
所在节点    程序员
14 条回复
eason1874
2019-11-24 05:58:28 +08:00
你用的什么 sdk ?我刚看了 ucloud 对象存储文档,他们放在 Github 的 PHP SDK 上传文件方法是 put,表单上传才是 post。

至于用 fopen 还是 file_get_contents,服务器那边分不出来,你改了报错说明你 file_get_contents 没用对。

各家厂商签名方法大多不一样,你拿这家 SDK 代码去请求另一家的接口,能用是巧合,报错才是常态。
lolizeppelin
2019-11-24 08:55:39 +08:00
put 和 post 最大区别在于 post 可以提交多个字段的内容,多个字段内容用&或者随机字符边界分割。


没有这个区别
duola
2019-11-24 09:32:22 +08:00
我的理解也是跟二楼的差不多。
loginv2
2019-11-24 10:17:46 +08:00
ucloud 的这个 SDK php 版本有问题,根本无法成功,估计也没人用,所以没人反馈
jinliming2
2019-11-24 13:17:57 +08:00
POST 和 PUT 本质上除了 method 不一样以外,没有任何区别
EminemW
2019-11-24 14:12:58 +08:00
PUT 和 POST 最大的区别难道不是:PUT 幂等,POST 不幂等
pinews
2019-11-24 18:33:01 +08:00
@EminemW 这里指实际应用,不是理念。
@lolizeppelin
@duola
@jinliming2 form 表单都不支持 put,论本质是 hack。
pinews
2019-11-24 18:34:41 +08:00
@pinews 在 curl 这里是被强制区分的。
xiaotuzi
2019-11-25 08:23:11 +08:00
看了题主的内容,我同意 2 楼的。
get 和 post 都是指定的传输方式,就算 form 也得指定提交方式,默认是 get。
另外,如果 url 上携带了&拼接的参数,又使用 post 提交几个其他的参数,最后还是认为 post 提交。
get,post 都有提交多个参数,curl 直接把 post 提交的数组拼接成&的形式,然后再提交。
lolizeppelin
2019-11-25 11:42:27 +08:00
没有区别, 有区别的是服务端根据 rfc 标准如何处理,以及客户端(库)是如何处理的

a=1&b=2 可以在 url 后面,也可以在 body 里.
到底是在 url 里还是在 body 需要看客户端代码如何处理的
如果在 url 里还会受到服务器端包头长度限制的影响
lolizeppelin
2019-11-25 11:45:06 +08:00
@pinews

a=1&b=2 不一定要看作 form 表单, 服务器端也可以认为是 filter

按现在的流行 a=1&b=2 作为 filter,具体数据在 body 里以 json 存放
pinews
2019-11-26 00:26:56 +08:00
也许是楼上几位朋友没用 ucloud 的 phpsdk,而且对 curl 也不太了解,所以回避了我原文的问题,而是抓住我不太严谨的话语无限展开了。
第一,我说过了,如果你提交的是一个内容,或者你把多个内容当成一个内容去发送,在技术上当然可以没有区别。我认为这是一种退步,因为已经给你提供多个内容的方法,你弃之不用,自己造轮子。

第二,post,对于文件类型,用&分割内容不合适了,而是用的随机字符做边界,哪怕你只有一个文件内容。而 put 本身是针对一个内容的,当然没有&也不会有随机字符边界,这时候按标准是不一样的。

第三 curl 在上传文件时,post 和 put 不仅对文件的要求不一样(一个是文件内容,一个是文件句柄),接受方法也不一样(一个是 postfield,一个是 READATA )

第四,ucloud 虽然能用,但是错的,之所以能用就是从客户端技术上没区别的,而服务器端也没有验证。

第五,我的错误在于没有认识到有价值的回答藏于深海,浮躁的回答飘荡于风中。
pinews
2019-11-26 00:34:32 +08:00
我猜测一个原因在于不做分割的情况下,post 只适合小文件传输,所以直接读取了文件全部内容,而 put 可以做大文件传输,不适合读取全部内容到内存中,而是提供了一个文件句柄,可以在传输过中一边读取,一边传输一边读取。
大概是这样吧。。。。。
encro
2019-12-16 08:59:44 +08:00
好像 POST 和 PUT 唯一区别在头:
PUT URL, POST URL

一般 Post 用于新增,PUT 用于修改

这是一个专为移动设备优化的页面(即为了让你能够在 Google 搜索结果里秒开这个页面),如果你希望参与 V2EX 社区的讨论,你可以继续到 V2EX 上打开本讨论主题的完整版本。

https://www.v2ex.com/t/622536

V2EX 是创意工作者们的社区,是一个分享自己正在做的有趣事物、交流想法,可以遇见新朋友甚至新机会的地方。

V2EX is a community of developers, designers and creative people.

© 2021 V2EX