有个产品需要上传图片到贴图库。为此还开了个贴图库的会员。
用的方案是ueditor+贴图库插件,自己加了个从dz拉过来的前端上传控件,然后禁用了Ueditor的上传按钮,毕竟数据先过一次后端再到贴图库是很蛋疼的事情。
决定禁用的关键是,贴图库给出的插件还是远程拉图模式,也就是说,产品有CDN,图片先从用户手里到达服务器tmp目录,Ueditor保存到upload目录,贴图库再访问cdn抓图,图片还得从Cdn过一遍,而Cdn有时不及时抓取,则导致贴图库抓不到文件,心累。
禁用后,发现Ueditor本地上传目录还是老是有文件出现,很是奇怪,今天下午干脆研究一下,试了多种方式最后猜测到是直接拖动图片到编辑器会导致上传行为。
本想直接改前端,把前端上传行为转向贴图库,后来放弃,还是先从后台着手解决。
发现贴图库sdk里明明有post上传的函数,却不用,改了一下,发现硬是传不上去。
原来Curl的Post发送文件,在Centos下会有问题,国外的大神给出了解决方案,竟然是自写Curl的Body部份,心疼
关键函数: 这里$assoc是正常post数据数组,$files是文件数据数组(文件地址值不要再加@了,里面有file_get_contents)
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 |
function curl_custom_postfields($ch, $assoc = array(), $files = array()) { // invalid characters for "name" and "filename" static $disallow = array("\0", "\"", "\r", "\n"); // build normal parameters foreach ($assoc as $k => $v) { $k = str_replace($disallow, "_", $k); $body[] = implode("\r\n", array( "Content-Disposition: form-data; name=\"{$k}\"", "", filter_var($v), )); } // build file parameters foreach ($files as $k => $v) { switch (true) { case false === $v = realpath(filter_var($v)): case !is_file($v): case !is_readable($v): continue; // or return false, throw new InvalidArgumentException } $data = file_get_contents($v); $v = call_user_func("end", explode(DIRECTORY_SEPARATOR, $v)); $k = str_replace($disallow, "_", $k); $v = str_replace($disallow, "_", $v); $body[] = implode("\r\n", array( "Content-Disposition: form-data; name=\"{$k}\"; filename=\"{$v}\"", "Content-Type: image/jpeg", //这里根据我自己需求修改的,貌似随便改别的也并不影响,起码贴图库不管 "", $data, )); } // generate safe boundary do { $boundary = "---------------------" . md5(mt_rand() . microtime()); } while (preg_grep("/{$boundary}/", $body)); // add boundary for each parameters array_walk($body, function (&$part) use ($boundary) { $part = "--{$boundary}\r\n{$part}"; }); // add final boundary $body[] = "--{$boundary}--"; $body[] = ""; // set options return @curl_setopt_array($ch, array( CURLOPT_POST => true, CURLOPT_POSTFIELDS => implode("\r\n", $body), CURLOPT_HTTPHEADER => array( "Expect: 100-continue", "Content-Type: multipart/form-data; boundary={$boundary}", // change Content-Type ), )); } |
方法怎么调用: 贴图库sdk的是post,我加了个postPlus
1 2 3 4 5 6 7 8 9 10 11 12 13 14 |
function postPlus($url,$postA,$postB){ $ch = curl_init(); curl_setopt($ch, CURLOPT_URL, $url); curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1); curl_setopt($ch, CURLOPT_BINARYTRANSFER,true); curl_setopt($ch, CURLOPT_TIMEOUT,30); $this->curl_custom_postfields($ch, $postA, $postB); //这里是关键 $output = curl_exec($ch); curl_close($ch); return $output; } |
还需要修改贴图库sdk的上传方法
1 2 3 4 5 6 7 8 9 |
function uploadFile($aid,$file=null){ $url = $this->upload_host; $param['deadline'] = time()+$this->timeout; $param['aid'] = $aid; $Token=$this->op_Token->dealParam($param)->createToken(); $data['Token']=$Token; $data1['file']=$file; //这里区分开来,文件数组 return empty($file)?$Token:$this->postPlus($url,$data,$data1); } |
最后修改Ueditor+贴图库的 Uploader.class.php,原本的uploadFromWeb改为uploadFile,直接丢临时文件$this->file[“tmp_name”]进去,再把Ueditor的move_uploaded_file处理注释掉,返回的stateInfo强制改为SUCCESS,完工!