微信开发上传图文消息内的图片(只返回图片URL),报错41005 缺少多媒体文件数据?(已解决)

这是添加素材的方法

    function addMaterial() {
        $img_size=filesize("图片");
        $file_info = array(
                /* 'name'=>'media', */
                'filename' => '/路径/Public/qf1.png', //图片相对于网站根目录的路径
                'content-type' => 'image/png', //文件类型
                'filelength' => $img_size //图文大小
        );
        $access_token = $this->getWxAccessToken();    
        $url = "https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token=".$access_token/*."&type=image"*/;
        $real_path = "{$_SERVER['DOCUMENT_ROOT']}{$file_info['filename']}";
        $data = array("media" => "@{$real_path}", 'form-data' => $file_info);
        $postJson=json_encode( $data );
        $res = $this->https_request( $url ,'post', 'json',$postJson);
        dump($res); 
    }

说明:
1.上面url后面type的组装,我看官网没有,然后网上找的,有人说加上类型,可是也没用。
返回报错信息
2.file_info里的 'name'=>'media',也是看别人说的要加上,但是也没用

3.去掉type和info里的name也一样。

报错信息如下

array(2) {
  ["errcode"] => int(41005)
  ["errmsg"] => string(41) "media data missing hint: [cjkOBa0678e298]"
}

请问哪里出了问题了?网上看到有个说法,说是和PHP版本有关系?

附1:调用接口的方法

    function https_request($url,$type="get",$res="json",$data = ''){
        //1.初始化curl
        $curl = curl_init();
        //2.设置curl的参数
        curl_setopt($curl, CURLOPT_URL, $url);
        curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
        curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,2);
        curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
        if ($type == "post"){
            curl_setopt($curl, CURLOPT_POST, 1);
            curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
        }
        //3.采集
        $output = curl_exec($curl);
        //4.关闭
        curl_close($curl);
        if ($res == 'json') {
            return json_decode($output,true);
        }
    }    

说明:curl_setopt($curl, CURLOPT_SSL_VERIFYHOST,2);//我这边设置成false或者0会不起作用...、

附2:获得微信的access_token

    function getWxAccessToken(){
        if ( $_SESSION['access_token'] && $_SESSION['expire_time'] > time() ) {
            //未过期
            return $_SESSION['access_token'];
        }else {
            $appid        = "我的id";
            $appsecret = "我的appsecret ";
            $url          = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$appsecret;
            $res =$this->https_request($url,'get','json');
            $access_token = $res["access_token"];
            //将重新获取到的access_token存到session里
            $_SESSION['access_token']=$access_token;
            $_SESSION['expire_time']=time()+7200;
            return $access_token; 
        }
    }

问题已经解决。
1.传递媒体参数只需要文件名即可。(相对入口文件根目录的路径开始,到文件的名称)
2.不需要json_encode
附上修改后的代码

    //上传图片素材(该方法只能获取到图片的URL)     2016-11-3
    function addMaterialUrl() {
        $access_token = $this->getWxAccessToken();    
        $url = "https://api.weixin.qq.com/cgi-bin/media/uploadimg?access_token=".$access_token;
        $filename = '我是图片';
        $data=array("media"=>'@'. $filename);
        $res=$this->https_request( $url ,'post', 'json', $data);
        //dump($res); exit();
        return $res['url'];
    }
附录:网友遇到同类问题原因
1.php版本的问题
用curl上传图片到微信来获取media一直失败,5.5.0没问题,5.6就出问题了,原来 CURL CURLOPT_POSTFIELDS 
PHP 5.5.0 中添加,默认值FALSE。 php 5.6.0 改默认值为 TRUE。
TRUE 禁用 @ 前缀在CURLOPT_POSTFIELDS 中发送文件。 意味着 @ 可以在字段中安全得使用了。 可使用 CURLFile 作为上传的代替。
阅读 12k
4 个回答

表示之前遇到过同样的情况,但是没有做记录,坏习惯坏习惯。
首先,可以先尝试使用微信的测试工具试一下。虽然接口是有改过的,接口要求也不太一样,例如图片大小,但是可以排除某些其他因素,如图片是否已损坏之类的。我用本机的一张png图片在测试工具测试了一下,提示文件格式有问题,所以我换了一张jpg格式。测试结果通过。
在保证了图片一定可以上传的前提之后。再开始码php。
我用你的代码测了一下,结果是跟你一样。我本机装了PHP5.5.6版本和7.0.9版本,两个版本都是不行的(windows下,linux没有测过)。然后就是各种更改数据,切换版本。

其中出了两个问题
deprecated: curl_setopt(): The usage of the @filename API for file uploading is deprecated. Please use the CURLFile class instead in ...
这个问题就是PHP的版本问题,你有查过资料应该清楚是PHP5.5以后的版本问题。可以通过两种方式解决
1、curl_setopt ($curl, CURLOPT_SAFE_UPLOAD, false);
2、"media" => new CURLFile(realpath($real_path)),
我采用第二种(保险起见两个都写上也可以),PHP版本向后兼容好点。

另外一个问题,也是关键所在。
是我在修改set_curlopt的时候,发现无论怎么修改,其实都是请求成功的,我说的是http code是200(curl_getinfo可以查看),所以应该是数据格式有问题。所以我回头看了一下你请求的数据$postJson。发现你既然请求的是json格式,为什么没有设置头部的请求格式。我设置了,然而并没有什么卵用。然后我直接用数组作为请求的数据。ok!这下终于行了。我不清楚你为什么要把数据设置成json格式,可能是微信其他接口误导了。
我建议你回头看一下手册上关于curl的部分。

期间我也是有查资料。百度就算了。全都是复制黏贴,有些连PHP版本都没有提及。谷歌了一下,可能是微信是中国的,收录的内容也差不了多少。结果还是失望。果然太容易得到的不会是好东西。

以上是我的思路,虽然废话很多,也不一定全对。你的代码我并没有多大改动,回头你自己试一下。
希望对你有帮助。
以下是代码

session_start();

function addMaterial($real_path) {
    if( !file_exists($real_path) ) {
        die('图片不存在');
    }

    $access_token = getWxAccessToken();
    echo $access_token.'<br />';
    $url = "https://api.weixin.qq.com/cgi-bin/media/upload?access_token=".$access_token."&type=image";
    echo $url.'<br />';

    $data = array(
        "media" => new CURLFile(realpath($real_path)),
//    'media' => '@'.$real_path,
    );
//    $data = array("media" => "@".$real_path);
    var_dump($data);
    echo '<br />';
    $postJson = $data;
//    $postJson=json_encode( $data );
//    $postJson = http_build_query($data);
    var_dump($postJson);
    $res = https_request( $url ,'post', 'json',$postJson);
    var_dump($res);
}

function https_request($url,$type="get",$res="json",$data = ''){
    //1.初始化curl
    $curl = curl_init();
    //2.设置curl的参数
    curl_setopt($curl, CURLOPT_URL, $url);
    curl_setopt ($curl, CURLOPT_SAFE_UPLOAD, false);
    curl_setopt($curl, CURLOPT_SSL_VERIFYPEER, FALSE);
    curl_setopt($curl, CURLOPT_SSL_VERIFYHOST, FALSE);
    curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1);
    if ($type == "post"){
        curl_setopt($curl, CURLOPT_POST, 1);
        curl_setopt($curl, CURLOPT_POSTFIELDS, $data);
    }
    //3.采集
    $output = curl_exec($curl);
    var_dump(curl_getinfo($curl));

    //4.关闭
    curl_close($curl);
    if ($res == 'json') {
        return json_decode($output,true);
    }
}

function getWxAccessToken(){
    if ( isset($_SESSION['access_token']) && $_SESSION['expire_time'] > time() ) {
        //未过期
        return $_SESSION['access_token'];
    }else {
        $appid        = "";
        $appsecret = "";
        $url          = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$appsecret;
        $res = https_request($url,'get','json');
        $access_token = $res["access_token"];
        //将重新获取到的access_token存到session里
        $_SESSION['access_token']=$access_token;
        $_SESSION['expire_time']=time()+7200;
        return $access_token;
    }
}


//addMaterial();
if( !file_exists(realpath($_SERVER['DOCUMENT_ROOT'].'/wechat_upload/qf1.jpg')) ) {
    die('不存在');
}

addMaterial($_SERVER['DOCUMENT_ROOT'].'/wechat_upload/qf1.jpg');

先确保curl没问题

clipboard.png

这是上传 一定要确定图片能被获取到 看看图片的地址 确保没问题
clipboard.png

新手上路,请多包涵

json 你能post过去?本地自己测过?

撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
1 篇内容引用
推荐问题
宣传栏