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

PHP 里 curl POST 提交文件到底应该怎么写呀

  •  
  •   mashirozx · 23 天前 · 2141 次点击

    想用 PHP 上传文件到图床(只接受 form data ),普通的 curl 是这样的,正常:

    curl \
      -F "[email protected]" \
      -H "Content-Type: multipart/form-data" \
      https://sm.ms/api/v2/upload
    

    但是用 PHP 一写,返回的都是 bool(false)string(0) ""

    <?php
    
    $url = "https://sm.ms/api/v2/upload";
    $headers = array();
    array_push($headers, "Content-Type: multipart/form-data");
    array_push($headers, "User-Agent: ".$_SERVER['HTTP_USER_AGENT']);
    
    // $fields = array('smfile' => curl_file_create('test.png', 'image/png', 'test.png'));
    $fields = array('smfile' => new CURLFile('test.png', 'image/png', 'tset.png'));
    
    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL, $url);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, false);
    curl_setopt($ch, CURLOPT_POST, true);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);
    
    var_dump(curl_exec($ch));
    var_dump(curl_error($ch));
    
    

    求助ヽ(*。>Д<)o゜

    15 回复  |  直到 2019-11-20 18:14:21 +08:00
        1
    pota   23 天前
    $fields = array('smfile' => "@favicon-original.png");
        2
    mashirozx   23 天前
    @pota #1 试了这样的写法,但是接口返回的是资源无效。检查了 curl 的 request header,发现 ["content_type"]=> string(24) "text/html; charset=UTF-8",header 里面的 size_upload 大小好像也太小了,不像是图片,所以看起来好像图片并没有被上传,只是上传了 @favicon-original.png 几个字?萌新我不是太懂,请耐心~
        4
    mashirozx   23 天前 via Android
    @young 我要是在 Google 查到解决方法就不会在这里问了
        5
    pota   23 天前
        6
    royantar   23 天前
    User-Agent 随便填一些字符试试,别用$_SERVER['HTTP_USER_AGENT']。
        7
    justfindu   23 天前
    试试文件使用绝对地址
        8
    pota   23 天前   ♥ 1
    ```
    <?php

    $url = "https://sm.ms/api/v2/upload";
    $headers = array();
    array_push($headers, "Content-Type: multipart/form-data");
    //agent 我复制的我浏览器的 你换乘你对应的就行了
    array_push($headers, "User-Agent: Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_6) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36");
    $file_path = 'your file path';
    if (function_exists('curl_file_create')) {
    $cFile = curl_file_create($file_path);
    } else { //
    $cFile = '@' . realpath($file_path);
    }
    $fields = array('smfile' => $cFile);

    $ch = curl_init();
    curl_setopt($ch, CURLOPT_URL,$url);
    curl_setopt($ch, CURLOPT_POST,1);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $post);
    curl_setopt($ch, CURLOPT_HTTPHEADER, $headers);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $fields);

    $result=curl_exec ($ch);
    curl_close($ch);

    var_dump(curl_exec($ch));
    ```
        9
    liuxu   23 天前
    google: sm.ms 403

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

    ```bash
    liuxu:/tmp$ cat post.php
    <?php

    $ch = curl_init();
    $fd = curl_file_create('/home/liuxu/Downloads/1.png', 'image/png', '1.png');
    $file = array('smfile' => $fd);

    curl_setopt($ch, CURLOPT_URL, "https://sm.ms/api/v2/upload");
    curl_setopt($ch, CURLOPT_VERBOSE, 1);
    curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, false);
    curl_setopt($ch, CURLOPT_HTTPHEADER, array('Content-Type: multipart/form-data', 'User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36'));
    curl_setopt($ch, CURLOPT_POST, 1);
    curl_setopt($ch, CURLOPT_RETURNTRANSFER, true);
    curl_setopt($ch, CURLOPT_POSTFIELDS, $file);
    $rs = curl_exec($ch);
    curl_close($ch);
    var_dump($rs);
    ?>
    liuxu:/tmp$ php post.php
    * Trying 47.88.229.110...
    * TCP_NODELAY set
    * Connected to sm.ms (47.88.229.110) port 443 (#0)
    * ALPN, offering http/1.1
    * successfully set certificate verify locations:
    * CAfile: /etc/ssl/certs/ca-certificates.crt
    CApath: /etc/ssl/certs
    * SSL connection using TLSv1.3 / TLS_AES_256_GCM_SHA384
    * ALPN, server accepted to use http/1.1
    * Server certificate:
    * subject: OU=Domain Control Validated; OU=ShinoSaki MDV; CN=sm.ms
    * start date: Jan 2 00:00:00 2017 GMT
    * expire date: Jan 2 23:59:59 2020 GMT
    * subjectAltName: host "sm.ms" matched cert's "sm.ms"
    * issuer: C=GB; ST=Greater Manchester; L=Salford; O=COMODO CA Limited; CN=COMODO RSA Domain Validation Secure Server CA
    * SSL certificate verify ok.
    > POST /api/v2/upload HTTP/1.1
    Host: sm.ms
    Accept: */*
    User-Agent: Mozilla/5.0 (X11; Linux x86_64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/78.0.3904.97 Safari/537.36
    Content-Length: 59028
    Content-Type: multipart/form-data; boundary=------------------------0dc5337c392dd914
    Expect: 100-continue

    < HTTP/1.1 100 Continue
    < HTTP/1.1 200 OK
    < Server: nginx
    < Date: Thu, 14 Nov 2019 08:02:36 GMT
    < Content-Type: text/html; charset=UTF-8
    < Transfer-Encoding: chunked
    < Connection: keep-alive
    < Vary: Accept-Encoding
    < Set-Cookie: PHPSESSID=1qsrkiqn676norodn0qnl3peln; path=/
    < Expires: Thu, 19 Nov 1981 08:52:00 GMT
    < Cache-Control: no-store, no-cache, must-revalidate
    < Pragma: no-cache
    < Strict-Transport-Security: max-age=63072000; includeSubDomains; preload
    < X-Frame-Options: SAMEORIGIN
    < X-Content-Type-Options: nosniff
    < X-XSS-Protection: 1; mode=block
    < X-Custom-Job: If you see this, please contact [email protected] for a job
    < Access-Control-Allow-Origin: *
    < Access-Control-Allow-Methods: OPTIONS, HEAD, GET, POST
    < Allow: GET, POST, HEAD
    < Set-Cookie: cid=rBWawl3NChysdVkoQsGLAg==; expires=Thu, 31-Dec-37 23:55:55 GMT; domain=sm.ms; path=/
    <
    * Connection #0 to host sm.ms left intact
    string(481) "{"success":true,"code":"success","message":"Upload success.","data":{"file_id":0,"width":715,"height":645,"filename":"1.png","storename":"rng9GNzEhBCMUQA.png","size":58844,"path":"\/2019\/11\/14\/rng9GNzEhBCMUQA.png","hash":"QChs79nUXbdZW6ygYDVOBvjGNe","url":"https:\/\/i.loli.net\/2019\/11\/14\/rng9GNzEhBCMUQA.png","delete":"https:\/\/sm.ms\/delete\/QChs79nUXbdZW6ygYDVOBvjGNe","page":"https:\/\/sm.ms\/image\/rng9GNzEhBCMUQA"},"RequestId":"3985A52B-A6C8-4F22-A96A-749E3C77D35E"}"

    ```
        10
    liuxu   23 天前   ♥ 1
    实际上 CURLOPT_POSTFIELDS 不需要设置 content-type 为 multipart-data

    https://www.php.net/manual/zh/function.curl-setopt.php

    CURLOPT_POSTFIELDS 全部数据使用 HTTP 协议中的 "POST" 操作来发送。 要发送文件,在文件名前面加上 @前缀并使用完整路径。 文件类型可在文件名后以 ';type=mimetype' 的格式指定。 这个参数可以是 urlencoded 后的字符串,类似'para1=val1&para2=val2&...',也可以使用一个以字段名为键值,字段数据为值的数组。 如果 value 是一个数组,Content-Type 头将会被设置成 multipart/form-data。 从 PHP 5.2.0 开始,使用 @ 前缀传递文件时,value 必须是个数组。 从 PHP 5.5.0 开始, @ 前缀已被废弃,文件可通过 CURLFile 发送。 设置 CURLOPT_SAFE_UPLOAD 为 TRUE 可禁用 @ 前缀发送文件,以增加安全性。
        11
    Rekkles   23 天前
    如果你用了 composer 那么请 google guzzle 的 document,
    如果没有,请使用 postman 模拟请求,成功之后 postman 可以导出代码
    完。
        12
    mashirozx   23 天前
    @liuxu #10 中午折腾了半天 @ 前缀,原来是和 PHP 版本有关!按您说的换了一个 UA 就成功了😂👍
        13
    mashirozx   23 天前
    @pota #5 中午我也看到这个帖子了,我这边是 PHP 7.2,按照 @liuxu #10 说的,不能直接那样写~ 不过还是很感谢你啦 o(* ̄▽ ̄*)o
        14
    mashirozx   23 天前
    @Rekkles #11 没用 composer~ 以后用到会注意的~
        15
    micookie   17 天前 via Android
    file_get_contens 也可以实现 post 请求,比起来变态的 curl 好多了
    关于   ·   FAQ   ·   API   ·   我们的愿景   ·   广告投放   ·   感谢   ·   实用小工具   ·   2028 人在线   最高记录 5043   ·     Select Language
    创意工作者们的社区
    World is powered by solitude
    VERSION: 3.9.8.3 · 21ms · UTC 02:36 · PVG 10:36 · LAX 18:36 · JFK 21:36
    ♥ Do have faith in what you're doing.