PHP如何将图片文件上传到另外一台服务器上


Posted in PHP onAugust 26, 2019

说,我有一个需求,就是一个临时功能。由于工作开发问题,我们有一个B项目,需要有一个商品添加的功能,涉及到添加商品内容,比如商品名字,商品描述,商品库存,商品图片等。后台商品添加的接口已经写完了,但是问题是目前没有后台页面,就是产品还没有出后台详细页面。前端已经完备了,上线了。后台还需要工作时间处理。所以目前的处理方法是在我们已经存在的A项目后台中,添加一个对B项目添加商品的功能。

PHP如何将图片文件上传到另外一台服务器上

一、当下问题

1、在我们已有的A项目中,新增一个添加商品的功能,这个本来是没有什么问题的,因为目前A项目中本身就已经连接了B项目的数据库,所以商品属性的新增和修改都没什么问题。主要是商品图片的上传这里,有点问题。B项目已经对外提供了上传图片的接口,但是由于我确实对前端不是特别熟悉。所以在A项目中的后台JS中调取B项目的上传图片的接口时,一直提示"CORS",这里应该是存在一个跨域的问题,虽然我PHP接口端已经对跨域做了处理(入口文件处),但是貌似JS这边也需要相应的调整。

PHP如何将图片文件上传到另外一台服务器上

// [ 应用入口文件 ]
//入口文件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,发现确实没有什么问题,于是就准备如此处理。

PHP如何将图片文件上传到另外一台服务器上

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:\Windows\php73CE.tmp"
 ["error"] => int(0)
 ["size"] => int(355565)
 }
}

5、所以按刚才设想的,简单做下转发还是不行,这里面参数的传输方式应该还有另外一种,就是文件的类型。鉴于是通过Postman方式上传成功,这个工具确实很推荐多多学习,他不仅作为一个第三方中间为我们验证接口是否可用,更给我们提供了调取接口的各种代码Damo,如图3中标识的Code处,就是获取Damo的按钮。我们点击可以看见Postman给我提供了三种,调取接口的方式。

<?php
//1、HttpRequest 发送http请求
$request = new HttpRequest();
$request->setUrl('http://jszapi.dev.jingjinglego.com/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.com',
 '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('http://jszapi.dev.jingjinglego.com/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.com',
 '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 => "http://jszapi.dev.jingjinglego.com/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.com",
 "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项目,然后返回图片路径,不就可以了吗。于是我有推了一遍,发现没有疏忽。于是觉得应该是解决了。

PHP如何将图片文件上传到另外一台服务器上

三、解决图片上传问题

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);
  if($res['data']){
   $return = ['code'=>1,'message'=>'成功','data'=>'jszapi.dev.jingjinglego.com'.$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如何将图片文件上传到另外一台服务器上,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对三水点靠木网站的支持!
如果你觉得本文对你有帮助,欢迎转载,烦请注明出处,谢谢!

PHP 相关文章推荐
require(),include(),require_once()和include_once()的异同
Jan 02 PHP
简单的php 验证图片生成函数
May 21 PHP
php 接口类与抽象类的实际作用
Nov 26 PHP
php错误、异常处理机制(补充)
May 07 PHP
php数据结构与算法(PHP描述) 快速排序 quick sort
Jun 21 PHP
php 操作数组(合并,拆分,追加,查找,删除等)
Jul 20 PHP
PHP 使用pcntl和libevent 实现Timer功能
Oct 27 PHP
让PHP显示Facebook的粉丝数量方法
Jan 08 PHP
跟我学Laravel之请求(Request)的生命周期
Oct 15 PHP
thinkPHP5.0框架引入Traits功能实例分析
Mar 18 PHP
PHP实现git部署的方法教程
Dec 19 PHP
thinkphp框架实现路由重定义简化url访问地址的方法分析
Apr 04 PHP
PHP命名空间与自动加载机制的基础介绍
Aug 25 #PHP
php的命名空间与自动加载实现方法
Aug 25 #PHP
PHP7数组的底层实现示例
Aug 25 #PHP
PHP实现cookie跨域session共享的方法分析
Aug 23 #PHP
php常用经典函数集锦【数组、字符串、栈、队列、排序等】
Aug 23 #PHP
php中错误处理操作实例分析
Aug 23 #PHP
php+js实现的无刷新下载文件功能示例
Aug 23 #PHP
You might like
ajax+php打造进度条 readyState各状态
2010/03/20 PHP
PHP去掉从word直接粘贴过来的没有用格式的函数
2012/10/29 PHP
PHP简单实现记录网站访问量功能示例
2018/06/06 PHP
thinkPHP+mysql+ajax实现的仿百度一下即时搜索效果详解
2019/07/15 PHP
laravel5表单唯一验证的实例代码
2019/09/30 PHP
TP5框架实现签到功能的方法分析
2020/04/05 PHP
JQUBar 基于JQUERY的柱状图插件
2010/11/23 Javascript
读jQuery之九 一些瑕疵说明
2011/06/21 Javascript
使用Jquery实现点击文字后变成文本框且可修改
2013/09/21 Javascript
巧用js提交表单轻松解决一个页面有多个提交按钮
2013/11/17 Javascript
jQuery中scrollTop()方法用法实例
2015/01/16 Javascript
jquery插件jquery.beforeafter.js实现左右拖拽分隔条对比图片的方法
2015/08/07 Javascript
js+css实现上下翻页相册代码分享
2015/08/18 Javascript
jQuery+CSS实现滑动的标签分栏切换效果
2015/12/17 Javascript
全国省市二级联动下拉菜单 js版
2016/05/10 Javascript
JavaScript 基础函数_深入剖析变量和作用域
2016/05/18 Javascript
在web中js实现类似excel的表格控件
2016/09/01 Javascript
再谈javascript常见错误及解决方法
2016/09/16 Javascript
js 将input框中的输入自动转化成半角大写(税号输入框)
2017/02/16 Javascript
详解使用grunt完成requirejs的合并压缩和js文件的版本控制
2017/03/02 Javascript
vue高德地图之玩转周边
2017/06/16 Javascript
10行原生JS实现文字无缝滚动(超简单)
2018/01/02 Javascript
web页面和微信小程序页面实现瀑布流效果
2018/09/26 Javascript
vue+SSM实现验证码功能
2018/12/07 Javascript
详解一个小实例理解js原型和继承
2019/04/24 Javascript
js实现鼠标点击飘爱心效果
2020/08/19 Javascript
基于js实现的图片拖拽排序源码实例
2020/11/04 Javascript
[38:41]2014 DOTA2国际邀请赛中国区预选赛 LGD VS CNB
2014/05/22 DOTA
Python实现把utf-8格式的文件转换成gbk格式的文件
2015/01/22 Python
基于Python的XSS测试工具XSStrike使用方法
2017/07/29 Python
python图像和办公文档处理总结
2019/05/28 Python
python使用dlib进行人脸检测和关键点的示例
2020/12/05 Python
专升本个人自我评价
2013/12/22 职场文书
2014年度培训工作总结
2014/11/27 职场文书
民事二审代理词
2015/05/25 职场文书
分享一个vue实现的记事本功能案例
2022/04/11 Vue.js