300字范文,内容丰富有趣,生活中的好帮手!
300字范文 > centos用php上传文件 WBB - Centos下PHP无法Curl模拟Post上传文件的问题

centos用php上传文件 WBB - Centos下PHP无法Curl模拟Post上传文件的问题

时间:2021-04-21 05:39:50

相关推荐

centos用php上传文件 WBB - Centos下PHP无法Curl模拟Post上传文件的问题

有个产品需要上传图片到贴图库。为此还开了个贴图库的会员。

用的方案是ueditor+贴图库插件,自己加了个从dz拉过来的前端上传控件,然后禁用了Ueditor的上传按钮,毕竟数据先过一次后端再到贴图库是很蛋疼的事情。

决定禁用的关键是,贴图库给出的插件还是远程拉图模式,也就是说,产品有CDN,图片先从用户手里到达服务器tmp目录,Ueditor保存到upload目录,贴图库再访问cdn抓图,图片还得从Cdn过一遍,而Cdn有时不及时抓取,则导致贴图库抓不到文件,心累。

禁用后,发现Ueditor本地上传目录还是老是有文件出现,很是奇怪,今天下午干脆研究一下,试了多种方式最后猜测到是直接拖动图片到编辑器会导致上传行为。

本想直接改前端,把前端上传行为转向贴图库,后来放弃,还是先从后台着手解决。

发现贴图库sdk里明明有post上传的函数,却不用,改了一下,发现硬是传不上去。

原来Curl的Post发送文件,在Centos下会有问题,国外的大神给出了解决方案,竟然是自写Curl的Body部份,心疼

关键函数: 这里$assoc是正常post数据数组,$files是文件数据数组(文件地址值不要再加@了,里面有file_get_contents)

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

),

));

}

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

functioncurl_custom_postfields($ch,$assoc=array(),$files=array()){

// invalid characters for "name" and "filename"

static$disallow=array("\0","\"","\r","\n");

// build normal parameters

foreach($assocas$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($filesas$k=>$v){

switch(true){

casefalse===$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

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;

}

1

2

3

4

5

6

7

8

9

10

11

12

13

14

functionpostPlus($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的上传方法

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);

}

1

2

3

4

5

6

7

8

9

functionuploadFile($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;//这里区分开来,文件数组

returnempty($file)?$Token:$this->postPlus($url,$data,$data1);

}

最后修改Ueditor+贴图库的 Uploader.class.php,原本的uploadFromWeb改为uploadFile,直接丢临时文件$this->file[“tmp_name”]进去,再把Ueditor的move_uploaded_file处理注释掉,返回的stateInfo强制改为SUCCESS,完工!

喜欢 (21)or分享 (0)

本内容不代表本网观点和政治立场,如有侵犯你的权益请联系我们处理。
网友评论
网友评论仅供其表达个人看法,并不表明网站立场。