V2EX = way to explore
V2EX 是一个关于分享和探索的地方
现在注册
已注册用户请  登录
pinews
V2EX  ›  程序员

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

  •  
  •   pinews · 2019-11-24 04:50:02 +08:00 · 2907 次点击
    这是一个创建于 1587 天前的主题,其中的信息可能已经有所发展或是发生改变。
    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 最后在哪产生了分别。
    14 条回复    2019-12-16 08:59:44 +08:00
    eason1874
        1
    eason1874  
       2019-11-24 05:58:28 +08:00   ❤️ 1
    你用的什么 sdk ?我刚看了 ucloud 对象存储文档,他们放在 Github 的 PHP SDK 上传文件方法是 put,表单上传才是 post。

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

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


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

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

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

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

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

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

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

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

    一般 Post 用于新增,PUT 用于修改
    关于   ·   帮助文档   ·   博客   ·   API   ·   FAQ   ·   我们的愿景   ·   实用小工具   ·   5315 人在线   最高记录 6543   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.5 · 29ms · UTC 09:06 · PVG 17:06 · LAX 02:06 · JFK 05:06
    Developed with CodeLauncher
    ♥ Do have faith in what you're doing.