在微信服務號中開發上傳圖片功能php
後端 php yii2 前端javscript前端
1.https 域 下前端處理base64爲圖片,蘋果不支持。
2.七牛的fech接口很坑,有些數據不能存儲,隨機性的成功。ajax
1.經過微信的接口,調取手機的拍照和選取相冊很方即可以設置選擇幾張和原圖和縮略圖,而後上傳到微信的服務>器,返回一個media_id發送到後端,經過微信的文件媒體接口獲取數據(數據token只存在兩個小時),而後經過php
處理成base64位數據,上傳到七牛,七牛返回連接存儲在本地。
2.前端處理圖片到七牛返回發到後端json
<div class="page-group"> <div class="page"> <div class="content" style="background-color: white;"> <img src="/image/distant/distant-view.png" width="100%"> <div class="distant-click"> <?php if ($model->distant_view) { echo '<img id="distant-click-img" src="'.$model->distant_view.'" width="100%" alt="" />'; }else { echo '<img id="distant-click-img" src="/image/distant/distant-click.png" width="100%" alt="" />'; } ?> </div> <input type="hidden" id='token' value ="<?php echo $token;?>" name=""> <div class="wish-hider-next-button"> <span id="submit">下一步</span> </div> </div> </div> </div> <script> <?php $wechat = Yii::$app->wechat; ?> wx.config(<?php echo json_encode( $wechat->jsApiConfig( [ "jsApiList" => [ "onMenuShareTimeline", "onMenuShareAppMessage", "onMenuShareQQ", "onMenuShareWeibo", "chooseImage", 'uploadImage' ] ] ) ); ?>) Zepto(function($){ var obj = $('#distant-click-img'); var id = "<?=$id?>"; var _csrf = "<?= Yii::$app->request->getCsrfToken()?>"; var distant_src = $("#distant-click-img").attr('src'); var flag = 0; if(distant_src != '/image/distant/distant-click.png'){ flag = 1; } wx.ready(function() { 微信上傳代碼 // 點擊更換按鈕 $('#distant-click-img').click(function(){ wx.chooseImage({ count: 1, // 默認9 選擇幾張照片 sizeType: ['compressed'], // 能夠指定是原圖仍是壓縮圖,默認兩者都有 sourceType: ['album', 'camera'], // 能夠指定來源是相冊仍是相機,默認兩者都有 success: function (res) { var localIds = res.localIds; // 返回選定照片的本地ID列表,localId能夠做爲img標籤的src屬性顯示圖片 obj.attr('src',localIds) flag = 0; UpToWexinService(); } }); // 上傳圖片到微信服務器 function UpToWexinService() { var src = obj.attr('src'); wx.uploadImage({ localId: src, // 須要上傳的圖片的本地ID,由chooseImage接口得到 isShowProgressTips: 1, // 默認爲1,顯示進度提示 success: function (res) { // 把圖片保存在本身的服務器 saveImageInfo(res.serverId); } }); } }) /** * 上傳遠景圖片到本身的服務器 * @param [type] imgData [description] * @return [type] [description] */ function saveImageInfo(imgData) { $.ajax({ url:'save-distant-img-data', type:'post', data:{'id':id,'img':imgData,'_csrf':_csrf}, success:function(res){ if (res.data.status == 1) { flag = 1 $.toast(res.data.data); } else { $.toast(res.data.data); } }, error:function(res){ $.toast("圖片上傳錯誤"); } }) } }) }) </script>
注意 網站使用了https,蘋果手機不能處理。後端
/** * 上傳64位編碼到七牛 * @param [type] data [description] * @return [type] [description] */ function putb64(data){ var pic = data; var token = $('#token').val(); var url = "https://upload.qiniu.com/putb64/-1"; var xhr = new XMLHttpRequest(); xhr.onreadystatechange=function(){ if (xhr.readyState==4){ var str =JSON.parse(xhr.responseText) var srcImg = 'https://obf949end.qnssl.com/'+str.key; $('#distant-click-img').attr('src',srcImg); saveImageInfo(srcImg); } } xhr.open("POST", url, true); xhr.setRequestHeader("Content-Type", "application/octet-stream"); xhr.setRequestHeader("Authorization", "UpToken "+token); xhr.send(pic); }
七牛有點坑,說明很不明確,處理個圖片到七牛,找到兩個接口,fetch 和 pubtb64api
fetch 不穩定老是失敗,不知道是否是跨域或者攔截,感受不可靠。最終又改爲了pubtb64位處理的跨域
本身在開發的過程當中,各類百度,谷歌,不多有給全的代碼,都靠本身去猜。在這裏貼上所有代碼,節省你們時間。服務器
註釋儘可能加全,把全部的都集中在這裏 /** * 把圖片存在服務器上面 * @return [type] [description] */ public function actionSaveDistantImgData() { Yii::$app->response->format = Response::FORMAT_JSON; $request = Yii::$app->request; $data = $request->post(); $img = $data['img']; $id = $data['id']; // 獲取七牛的token $token = self::GetUploadToken(); $upToken = $token['token']; // 獲取微信的 access_token $weixin_token = \DockerEnv::get('WEIXIN_TOKEN'); $appid = \DockerEnv::get('WEIXIN_APP_ID'); $secret = \DockerEnv::get('WEIXIN_APP_SECRET'); $url_get = "https://api.weixin.qq.com/cgi-bin/token?grant_type=client_credential&appid=".$appid."&secret=".$secret; $json=$this->curlGet($url_get); $weixin_token = json_decode($json); $weixin_token=$weixin_token->access_token; // 從微信服務器下載 $str = "http://file.api.weixin.qq.com/cgi-bin/media/get?access_token=".$weixin_token."&media_id=".$img; // 把從微信得到的數據用七牛上傳到服務器上面 $access_key = \DockerEnv::get('QINIU_ACCESS_KEY'); $secret_key = \DockerEnv::get('QINIU_SECRET_KEY'); $this->request_by_curl($remote_server,$post_string,$upToken); $strr = file_get_contents($str); $fetch =base64_encode($strr); $imggg = $this->request_by_curl('http://upload.qiniu.com/putb64/-1',$fetch,$upToken); $imgs = json_decode(trim($imggg),true); $imgss = $imgs['hash']; $imgUrl = 'https://obf949end.qnssl.com/'.$imgss.'?imageslim'; // 把遠景數據存在試管表裏面 $test_tube = TestTube::findOne($id); $test_tube->distant_view = $imgUrl; $test_tube->save(); // 把遠景圖片存在藏匿者表裏 $solid_sneak = SolidSneak::find()->where(['test_tube_id' => $id])->one(); $solid_sneak->distant_view = $imgUrl; $solid_sneak->updated_at = time(); if ($solid_sneak->save()) { return ['status' => 1,'data' => '圖片上傳成功']; } return ['status' => 0,'data' => '圖片上傳失敗']; }
public function curlGet($url){ $ch = curl_init(); $header = "Accept-Charset: utf-8"; curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_CUSTOMREQUEST, "GET"); curl_setopt($ch, CURLOPT_SSL_VERIFYPEER, FALSE); curl_setopt($ch, CURLOPT_SSL_VERIFYHOST, FALSE); // curl_setopt($curl, CURLOPT_HTTPHEADER, $header); curl_setopt($ch, CURLOPT_USERAGENT, 'Mozilla/5.0 (compatible; MSIE 5.01; Windows NT 5.0)'); curl_setopt($ch, CURLOPT_FOLLOWLOCATION, 1); curl_setopt($ch, CURLOPT_AUTOREFERER, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $data); curl_setopt($ch, CURLOPT_RETURNTRANSFER, true); $temp = curl_exec($ch); return $temp; } public function send($url, $header = '') { $curl = curl_init($url); curl_setopt($curl, CURLOPT_RETURNTRANSFER, 1); curl_setopt($curl, CURLOPT_HEADER,0); curl_setopt($curl, CURLOPT_HTTPHEADER, $header); curl_setopt($curl, CURLOPT_POST, 1); $con = curl_exec($curl); if ($con === false) { echo 'CURL ERROR: ' . curl_error($curl); } else { return $con; } } public function urlsafe_base64_encode($str){ $find = array("+","/"); $replace = array("-", "_"); return str_replace($find, $replace, base64_encode($str)); } public function request_by_curl($remote_server,$post_string,$upToken) { $headers = array(); $headers[] = 'Content-Type:image/png'; $headers[] = 'Authorization:UpToken '.$upToken; $ch = curl_init(); curl_setopt($ch, CURLOPT_URL,$remote_server); //curl_setopt($ch, CURLOPT_HEADER, 0); curl_setopt($ch, CURLOPT_HTTPHEADER ,$headers); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); //curl_setopt($ch, CURLOPT_POST, 1); curl_setopt($ch, CURLOPT_POSTFIELDS, $post_string); curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 10); curl_setopt($ch, CURLOPT_TIMEOUT, 30); $data = curl_exec($ch); curl_close($ch); return $data; } /** * generate_access_token * * @desc 簽名運算 * @param string $access_key * @param string $secret_key * @param string $url * @param array $params * @return string */ public function generate_access_token($access_key, $secret_key, $url, $params = ''){ $parsed_url = parse_url($url); $path = $parsed_url['path']; $access = $path; if (isset($parsed_url['query'])) { $access .= "?" . $parsed_url['query']; } $access .= "\n"; if($params){ if (is_array($params)){ $params = http_build_query($params); } $access .= $params; } $digest = hash_hmac('sha1', $access, $secret_key, true); return $access_key.':'.$this->urlsafe_base64_encode($digest); } public function base64EncodeImage ($image_file) { $base64_image = ''; $image_info = getimagesize($image_file); $image_data = fread(fopen($image_file, 'r'), filesize($image_file)); $base64_image = 'data:' . $image_info['mime'] . ';base64,' . chunk_split(base64_encode($image_data)); return $base64_image; }