PHP如何将图⽚⽂件上传到另外⼀台服务器上
说,我有⼀个需求,就是⼀个临时功能。由于⼯作开发问题,我们有⼀个B项⽬,需要有⼀个商品添加的功能,涉及到添加商品内容,⽐如商品名字,商品描述,商品库存,商品图⽚等。后台商品添加的接⼝已经写完了,但是问题是⽬前没有后台页⾯,就是产品还没有出后台详细页⾯。前端已经完备了,上线了。后台还需要⼯作时间处理。所以⽬前的处理⽅法是在我们已经存在的A项⽬后台中,添加⼀个对B项⽬添加商品的功能。
⼀、当下问题
1、在我们已有的A项⽬中,新增⼀个添加商品的功能,这个本来是没有什么问题的,因为⽬前A项⽬中本⾝就已经连接了B项⽬的数据库,所以商品属性的新增和修改都没什么问题。主要是商品图⽚的上传这⾥,有点问题。B项⽬已经对外提供了上传图⽚的接⼝,但是由于我确实对前端不是特别熟悉。所以在A项⽬中的后台JS中调取B项⽬的上传图⽚的接⼝时,⼀直提⽰"CORS",这⾥应该是存在⼀个跨域的问题,虽然我PHP接⼝端已经对跨域做了处理(⼊⼝⽂件处),但是貌似JS这边也需要相应的调整。
// [ 应⽤⼊⼝⽂件 ]
//⼊⼝⽂件index.php
namespace think;
/
/ 加载基础⽂件
require __DIR__ . '/thinkphp/base.php';
// ⽀持事先使⽤静态⽅法设置Request对象和Config对象
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: Content-Type,XFILENAME,XFILECATEGORY,XFILESIZE,authorization");
// 执⾏应⽤并响应
Container::get('app')->bind('api')->run()->send();
2、⽆奈⼩⽩JS功底不够扎实,所以我这边准备通过A项⽬中调取后台PHP接⼝,然后通过在PHP代码中接受web端参数,然后再转发,调取B项⽬中上传图⽚的接⼝,试图完成功能。于是先通过Postman接⼝⼯具测试了⼀下B项⽬上传图⽚的接⼝是否有效。如图3,发现确实没有什么问题,于是就准备如此处理。
3、但是实际是,在调取时,我们常⽤的传参数⽅式是GET或者POST⽅式,但是我们知道⽂件上传是通过$_FILES接受,下⾯是B项⽬的上传图⽚的控制器代码(⽤的是TP5.1),接受是通过内置的file⽅式。
/**上传图⽚
* @param Request $request
*/
public function uploadImg(Request $request){
$file = $request->file('image');
$type = $request->post('type', 0);
// 移动到框架应⽤根⽬录/uploads/ ⽬录下
$upload_path = config('common.upload_path');
switch ($type) {
case 1://门店
$path = $upload_path['shop_img'];
break;
case 2://投票活动
$path = $upload_path['vote_img'];
break;
case 3://投票活动参赛图⽚
$path = $upload_path['vote_contestant_img'];
break;
case 4://会员店铺logo图⽚
$path = $upload_path['member_shop'];
break;
case 5://⾃营商品图⽚
$path = $upload_path['self_goods'];
break;
default:
$path = $upload_path['common'];
break;
}
$save_path = env('root_path').$path;
$info = $file->validate(['ext'=>'jpg,jpeg,png,gif'])->move($save_path);
if($info){
$return = [
'extension' => $info->getExtension(),
'image_path' => $path.$info->getSaveName(),
'image_name' => $info->getFilename(),
]
;
$this->apiResult(CustomError::OPERATION_SUCCSESS, $return);
}else{
$this->apiResult(CustomError::OPERATION_FAILED, [], $file->getError());
}
}
4、所以在转发A项⽬web端传来的,⽂件内容,就有点不知所措了。该死,该死。
//⽂件上传接受参数
array(1) {
["file_upload"] => array(5) {
["name"] => string(8) "timg.jpg"
["type"] => string(10) "image/jpeg"
["tmp_name"] => string(22) "C:\p"
["error"] => int(0)
["size"] => int(355565)
}
}
5、所以按刚才设想的,简单做下转发还是不⾏,这⾥⾯参数的传输⽅式应该还有另外⼀种,就是⽂件的类型。鉴于是通过Postman⽅式上传成功,这个⼯具确实很推荐多多学习,他不仅作为⼀个第
三⽅中间为我们验证接⼝是否可⽤,更给我们提供了调取接⼝的各种代码Damo,如图3中标识的Code处,就是获取Damo的按钮。我们点击可以看见Postman给我提供了三种,调取接⼝的⽅式。
<?php
//1、HttpRequest 发送http请求
$request = new HttpRequest();
$request->setUrl('jszapi.dev.jingjinglego/index.php/index/uploadImg');
$request->setMethod(HTTP_METH_POST);
$request->setHeaders(array(
'cache-control' => 'no-cache',
'Connection' => 'keep-alive',
'Content-Length' => '39091',
'Content-Type' => 'multipart/form-data; boundary=--------------------------296608706222243058746908',
'Accept-Encoding' => 'gzip, deflate',
'Host' => 'jszapi.dev.jingjinglego',
'Postman-Token' => 'dc010150-b166-4dec-a33f-959a65c91c71,be7315cb-ae21-404f-89fa-dddf5973eb3a',
'Cache-Control' => 'no-cache',
'Accept' => '*/*',
'User-Agent' => 'PostmanRuntime/7.15.2',
'content-type' => 'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW'
));
$request->setBody('------WebKitFormBoundary7MA4YWxkTrZu0gW
Content-Disposition: form-data; name="image"; filename="785da43beca5a474.jpg"
Content-Type: image/jpeg
------WebKitFormBoundary7MA4YWxkTrZu0gW--');
try {
$response = $request->send();
echo $response->getBody();
} catch (HttpException $ex) {
echo $ex;
}
<?php
//2、pecl_http 需要开启PECL HTTP 扩展
$client = new http\Client;
$request = new http\Client\Request;
$body = new http\Message\Body;
$body->addForm(NULL, array(
array(
'name' => 'image',
'type' => null,
'file' => '/E:/MyBooks/⽹站图标/⽹站素材/785da43beca5a474.jpg',
'data' => null
)
));
$request->setRequestUrl('jszapi.dev.jingjinglego/index.php/index/uploadImg');
$request->setRequestMethod('POST');
$request->setBody($body);
$request->setHeaders(array(
'cache-control' => 'no-cache',
'Connection' => 'keep-alive',
'Content-Length' => '39091',
'Content-Type' => 'multipart/form-data; boundary=--------------------------296608706222243058746908',
'Accept-Encoding' => 'gzip, deflate',
'Host' => 'jszapi.dev.jingjinglego',
'Postman-Token' => 'dc010150-b166-4dec-a33f-959a65c91c71,3216cc22-be61-4d4b-8d41-c5178848b54f',
'Cache-Control' => 'no-cache',
'Accept' => '*/*',
'User-Agent' => 'PostmanRuntime/7.15.2'
));
$client->enqueue($request)->send();
$response = $client->getResponse();
echo $response->getBody();
<?php
//3、cURL 是⼀个⾮常强⼤的开源库,⽀持很多协议,包括HTTP、FTP、TELNET等,我们使⽤它来发送HTTP请求。//它给我们带来的好处是可以通过灵活的选项设置不同的HTTP协议参数,并且⽀持HTTPS。CURL可以根据URL前缀是“HTTP” 还是“HTTPS”⾃动选$curl = curl_init();
curl_setopt_array($curl, array(
CURLOPT_URL => "jszapi.dev.jingjinglego/index.php/index/uploadImg",
CURLOPT_RETURNTRANSFER => true,
CURLOPT_ENCODING => "",
CURLOPT_MAXREDIRS => 10,
CURLOPT_TIMEOUT => 30,
CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
CURLOPT_CUSTOMREQUEST => "POST",
CURLOPT_POSTFIELDS => "------WebKitFormBoundary7MA4YWxkTrZu0gW\r\nContent-Disposition: form-data; name=\"image\"; filename=\"785da43beca5a474.jpg\"\r\nContent-Type: image/jpeg\r\n\r\n\r\n------WebKitFormBoundary7MA4YWxkTrZu0gW--",
CURLOPT_HTTPHEADER => array(
"Accept: */*",
"Accept-Encoding: gzip, deflate",
"Cache-Control: no-cache",
"Connection: keep-alive",
"Content-Length: 39091",
"Content-Type: multipart/form-data; boundary=--------------------------296608706222243058746908",
"Host: jszapi.dev.jingjinglego",
"Postman-Token: dc010150-b166-4dec-a33f-959a65c91c71,982e059e-bd8b-4db9-83c4-3fd52c8ed82f",
"User-Agent: PostmanRuntime/7.15.2",
"cache-control: no-cache",
"content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW"
),
));
$response = curl_exec($curl);
$err = curl_error($curl);
curl_close($curl);
if ($err) {
echo "cURL Error #:" . $err;
} else {
echo $response;
}
6、如上⾯3个代码⽚段,但是后来验证后,发现1/3的参数,不知道是怎么传输的,2的参数很容易看懂,但是运⽤的话需要开启扩展,这个⽬前不太合适,所以┭┮﹏┭┮。
⼆、写在⼼⾥
1、这个上传的问题,确实卡住了,感觉有点难过。其实每次都会遇见⼀个⾃⼰的困难,经常遇见,周末下午的时候,我在家打开电脑,打来远程,准备登陆下ftp拉下代码,发现⼀直连不上,⼼⾥那个烦啊。但是还是通过远程⼯具(向⽇葵),将代码拉下来了。想这个图⽚上传到底怎么弄了,之前也看过,关于通过ftp的⽅式上传图⽚,但是后来查看了相关⽂章需要在php.ini中开启,所以也作罢。
#开启ftp扩展⽀持
extension=php_ftp.dll
2、经常遇见困难,经常觉得⾃⼰很LOW但是,已经⼯作了这么久,发现其实问题最后⼜都解决了,但是现在回想,却忘了到底是怎么解决的,所以写这个博⽂主要也是想记录下。⼀直到下午4点多,深圳的天⽓今年闷热居多,中午我已经昧着良⼼午休了1个⼩时,所以现在到现在⼼⾥还有些许内疚,唉。
3、但是还是不到解决的⽅法,头疼的厉害,好热。怎么办,我决定靠在椅⼦上休息下,于是我还是决定躺在沙发上睡会。刚躺下,想着这怎么办呢。
-----------------------base64---------------------------华丽的分割线
我突然想到了base64这个读起来,朗朗上⼝的函数,对如果现将图⽚转换成base64字符串,再通过POST⽅式传送给B项⽬,然后再B项⽬中对字符串进⾏解码,⽣成图⽚,保存到B项⽬,然后返回图⽚路径,不就可以了吗。于是我有推了⼀遍,发现没有疏忽。于是觉得应该是解决了。
三、解决图⽚上传问题
1、A接受web传来图⽚临时⽂件,
#上传图⽚京⼿指 1:图⽚保留到本地
public function uploadJszImg()
{$path = config('business.jsz_file_tem');
$file = request()->file('file_upload');
$info = $file->validate(['ext'=>'jpg,jpeg,png,gif'])->move($path);//图⽚保存到本地
$img_one = $path.$info->getSaveName();//图⽚路径
$img_base = imgToBase64($img_one);//获取图⽚base64编码格式
deleteFileWay($path);//删除临时⽂件
$url = config('business.jsz_api')['baseImg'];
$data = [
'base_string'=> $img_base,
'path' => 'upload/goods_img',
];
$res = http_api($url,$data,1);
$res = json_decode($res,true);
getsavefilenameif($res['data']){
$return = ['code'=>1,'message'=>'成功','data'=>'jszapi.dev.jingjinglego'.$res['data']];
}else{
$return = ['code'=>0,'message'=>'失败'];
}
return $return;
}
2、并转换成base64字符串,
/**
* 获取图⽚的Base64编码(不⽀持url)
* @param $img_file 传⼊本地图⽚地址
* @return string
*/
function imgToBase64($img_file) {
$img_base64 = '';
if (file_exists($img_file)) {
$app_img_file = $img_file; // 图⽚路径
$img_info = getimagesize($app_img_file); // 取得图⽚的⼤⼩,类型等
//echo '<pre>' . print_r($img_info, true) . '</pre><br>';
$fp = fopen($app_img_file, "r"); // 图⽚是否可读权限
if ($fp) {
$filesize = filesize($app_img_file);
$content = fread($fp, $filesize);
$file_content = chunk_split(base64_encode($content)); // base64编码
switch ($img_info[2]) { //判读图⽚类型
case 1: $img_type = "gif";
break;
case 2: $img_type = "jpg";
break;
case 3: $img_type = "png";
break;
}
$img_base64 = 'data:image/' . $img_type . ';base64,' . $file_content;//合成图⽚的base64编码
}
fclose($fp);
}
return $img_base64; //返回图⽚的base64
}
3、B接受A项⽬传来参数
/**
* 将base64字符串转换成图⽚并保存在本地
* @param Request $request
* @return void
*/
public function baseImg(Request $request)
{
$base_string = $request->post('base_string', '');
if (!$base_string) {
$this->apiResult(CustomError::MISSING_PARAMS);
}
$path = $request->post('path', '');
if (!$path) {
$this->apiResult(CustomError::MISSING_PARAMS);
}
$request = base64_image_content($base_string, $path);//解码
if($request){
$this->apiResult(CustomError::OPERATION_SUCCSESS, $request);
}else{
$this->apiResult(CustomError::OPERATION_FAILED);
}
}
4、对字符解析解码
/**
* [将Base64图⽚转换为本地图⽚并保存]
* @param [Base64] $base64_image_content [要保存的Base64]
* @param [⽬录] $path [要保存的路径]
*/
function base64_image_content($base64_image_content,$path){
//匹配出图⽚的格式
if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64_image_content, $result)){
$type = $result[2];
$new_file = $path."/".date('Ymd',time())."/";
if(!file_exists($new_file)){
//检查是否有该⽂件夹,如果没有就创建,并给予最⾼权限
mkdir($new_file, 0700);
}
$new_file = $new_file.time().".{$type}";
if (file_put_contents($new_file, base64_decode(str_replace($result[1], '', $base64_image_content)))){
return '/'.$new_file;
}else{
return false;
}
}else{
return false;
}
}
5、最后返回上传好的图⽚路径
:结束
总结
以上所述是⼩编给⼤家介绍的PHP如何将图⽚⽂件上传到另外⼀台服务器上,希望对⼤家有所帮助,如果⼤家有任何疑问请给我留⾔,⼩编会及时回复⼤家的。在此也⾮常感谢⼤家对⽹站的⽀持!如果你觉得本⽂对你有帮助,欢迎转载,烦请注明出处,谢谢!
版权声明:本站内容均来自互联网,仅供演示用,请勿用于商业和其他非法用途。如果侵犯了您的权益请与我们联系QQ:729038198,我们将在24小时内删除。
发表评论