首页 > 解决方案 > 上传的文件在 guzzle json_encode 错误中使用 fopen 错误打开:不支持类型

问题描述

我无法附加上传的文件。我看到 fopen($image->getPathname(),'r') 返回不可转换的 json 数据类型,使 guzzle 返回错误 json_encode 错误:不支持类型。我在这里做错了什么?谢谢你。

stream resource @586 ▼
    timed_out: false
    blocked: true
    eof: false
    wrapper_type: "plainfile"
    stream_type: "STDIO"
    mode: "r"
    unread_bytes: 0
    seekable: true
    uri: "\Temp\php2D41.tmp"
    options: []


//use Illuminate\Support\Facades\Http;
//use Illuminate\Support\Facades\File;

if($request->hasFile('imgInp1'))
   {
    foreach(request('imgInp1') as $image)
    {
      $message = Http::post('https://graph.facebook.com/v9.0/me/message_attachments?access_token='.$access_token, 
                                [
                                    'headers' => [
                                        'Content-Type' => 'multipart/form-data',
                                    ],
                                    'multipart' => [
                                        'name'         => 'image',
                                        'image_path'   => $image->getPathname(),
                                        'image_mime'   => $image->getmimeType(),
                                        'image_org'    => $image->getClientOriginalName(),
                                        'contents'     => fopen($image->getPathname(), 'r'),
                                    ],
                                    'message'=>[
                                        'attachment' => [
                                            'type' => 'image',
                                            'payload' => [
                                                "is_reusable"=> true,
                                            ],
                                        ],
                                    ],
                                ]);
    }
  }

标签: phplaravelfacebook-graph-apiguzzle

解决方案


从您使用的 url,这是 facebook api_guide中提供的 curl 请求

curl  \
  -F 'message={"attachment":{"type":"image", "payload":{"is_reusable":true}}}' \
  -F 'filedata=@/tmp/shirt.png;type=image/png' \
  "https://graph.facebook.com/v9.0/me/message_attachments?access_token=<PAGE_ACCESS_TOKEN>"

这就是 -F 在 curl 中的含义

-F, --form <name=content>

 (HTTP SMTP IMAP) 对于 HTTP 协议族,这让 curl 模拟一个用户按下提交按钮的填充表单。这会导致 curl 根据 RFC 2388 使用 Content-Type multipart/form-data 发布数据。

(来源man curl:)

通过解释卷曲的第二行,

您还可以通过使用 'type=' 告诉 curl 要使用的 Content-Type,其方式类似于:
curl -F "web=@index.html;type=text/html" example.com

curl -F "name =daniel;type=text/foo" example.com

所以它告诉你需要多部分/表单数据。

我直接使用 guzzle 代替使用 HttpClient(在 laravel 中默认提供,来自 composer.json 的确认)。另外我建议使用 try catch 块,因为它不一定总是 200 响应。

$message["attachment"] = [
        "type" => "image",
        "payload"=> ["is_reusable"=>true]
    ];

try{
    $client = new \GuzzleHttp\Client();
    if(file_exists($image)){ // or can use \Illuminate\Support\Facades\File::exists($image)
        $request = $client->post( 'https://graph.facebook.com/v9.0/me/message_attachments?access_token='.$access_token, [
            // 'headers' => [],  //if you want to add some
            'multipart' => [
                [
                    'name' => 'message',
                    'contents' => json_encode($message),
                ],
                [
                    'Content-type' => $image->getmimeType(),
                    'name'     => 'filedata',
                    'contents' => fopen($image->getPathname(), 'r'),
                ]
            ]
        ]);
        if ($request->getStatusCode() == 200) {
             $response = json_decode($request->getBody(),true);
             //perform your action with $response 
        } 
    }else{
        throw new \Illuminate\Contracts\Filesystem\FileNotFoundException();
    }
}catch(\GuzzleHttp\Exception\RequestException $e){
    // see this answer for https://stackoverflow.com/questions/17658283/catching-exceptions-from-guzzle/64603614#64603614 
    // you can catch here 400 response errors and 500 response errors
    // see this https://stackoverflow.com/questions/25040436/guzzle-handle-400-bad-request/25040600
}catch(Exception $e){
    //catch other errors
}


推荐阅读