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

  

  一、当下问题

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

  1. // [ 应用入口文件 ]
  2. //入口文件index.php
  3. namespace think;
  4.  
  5. // 加载基础文件
  6. require __DIR__ . '/thinkphp/base.php';
  7.  
  8. // 支持事先使用静态方法设置Request对象和Config对象
  9. header("Access-Control-Allow-Origin: *");
  10. header("Access-Control-Allow-Headers: Content-Type,XFILENAME,XFILECATEGORY,XFILESIZE,authorization");
  11. // 执行应用并响应
  12. 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方式。

  1. /**上传图片
  2. * @param Request $request
  3. */
  4. public function uploadImg(Request $request){
  5. $file = $request->file('image');
  6. $type = $request->post('type', 0);
  7. // 移动到框架应用根目录/uploads/ 目录下
  8. $upload_path = config('common.upload_path');
  9. switch ($type) {
  10. case 1://门店
  11. $path = $upload_path['shop_img'];
  12. break;
  13. case 2://投票活动
  14. $path = $upload_path['vote_img'];
  15. break;
  16. case 3://投票活动参赛图片
  17. $path = $upload_path['vote_contestant_img'];
  18. break;
  19. case 4://会员店铺logo图片
  20. $path = $upload_path['member_shop'];
  21. break;
  22. case 5://自营商品图片
  23. $path = $upload_path['self_goods'];
  24. break;
  25. default:
  26. $path = $upload_path['common'];
  27. break;
  28. }
  29. $save_path = env('root_path').$path;
  30. $info = $file->validate(['ext'=>'jpg,jpeg,png,gif'])->move($save_path);
  31. if($info){
  32. $return = [
  33. 'extension' => $info->getExtension(),
  34. 'image_path' => $path.$info->getSaveName(),
  35. 'image_name' => $info->getFilename(),
  36. ];
  37. $this->apiResult(CustomError::OPERATION_SUCCSESS, $return);
  38. }else{
  39. $this->apiResult(CustomError::OPERATION_FAILED, [], $file->getError());
  40. }
  41. }

  4、所以在转发A项目web端传来的,文件内容,就有点不知所措了。该死,该死。

  1. //文件上传接受参数
  2. array(1) {
  3. ["file_upload"] => array(5) {
  4. ["name"] => string(8) "timg.jpg"
  5. ["type"] => string(10) "image/jpeg"
  6. ["tmp_name"] => string(22) "C:\Windows\php73CE.tmp"
  7. ["error"] => int(0)
  8. ["size"] => int(355565)
  9. }
  10. }

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

  1. <?php
  2. //1、HttpRequest 发送http请求
  3. $request = new HttpRequest();
  4. $request->setUrl('http://jszapi.dev.jingjinglego.com/index.php/index/uploadImg');
  5. $request->setMethod(HTTP_METH_POST);
  6.  
  7. $request->setHeaders(array(
  8. 'cache-control' => 'no-cache',
  9. 'Connection' => 'keep-alive',
  10. 'Content-Length' => '39091',
  11. 'Content-Type' => 'multipart/form-data; boundary=--------------------------296608706222243058746908',
  12. 'Accept-Encoding' => 'gzip, deflate',
  13. 'Host' => 'jszapi.dev.jingjinglego.com',
  14. 'Postman-Token' => 'dc010150-b166-4dec-a33f-959a65c91c71,be7315cb-ae21-404f-89fa-dddf5973eb3a',
  15. 'Cache-Control' => 'no-cache',
  16. 'Accept' => '*/*',
  17. 'User-Agent' => 'PostmanRuntime/7.15.2',
  18. 'content-type' => 'multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW'
  19. ));
  20.  
  21. $request->setBody('------WebKitFormBoundary7MA4YWxkTrZu0gW
  22. Content-Disposition: form-data; name="image"; filename="785da43beca5a474.jpg"
  23. Content-Type: image/jpeg
  24.  
  25. ------WebKitFormBoundary7MA4YWxkTrZu0gW--');
  26.  
  27. try {
  28. $response = $request->send();
  29.  
  30. echo $response->getBody();
  31. } catch (HttpException $ex) {
  32. echo $ex;
  33. }
  1. <?php
  2. //2、pecl_http 需要开启PECL HTTP 扩展
  3. $client = new http\Client;
  4. $request = new http\Client\Request;
  5.  
  6. $body = new http\Message\Body;
  7. $body->addForm(NULL, array(
  8. array(
  9. 'name' => 'image',
  10. 'type' => null,
  11. 'file' => '/E:/MyBooks/网站图标/网站素材/785da43beca5a474.jpg',
  12. 'data' => null
  13. )
  14. ));
  15.  
  16. $request->setRequestUrl('http://jszapi.dev.jingjinglego.com/index.php/index/uploadImg');
  17. $request->setRequestMethod('POST');
  18. $request->setBody($body);
  19.  
  20. $request->setHeaders(array(
  21. 'cache-control' => 'no-cache',
  22. 'Connection' => 'keep-alive',
  23. 'Content-Length' => '39091',
  24. 'Content-Type' => 'multipart/form-data; boundary=--------------------------296608706222243058746908',
  25. 'Accept-Encoding' => 'gzip, deflate',
  26. 'Host' => 'jszapi.dev.jingjinglego.com',
  27. 'Postman-Token' => 'dc010150-b166-4dec-a33f-959a65c91c71,3216cc22-be61-4d4b-8d41-c5178848b54f',
  28. 'Cache-Control' => 'no-cache',
  29. 'Accept' => '*/*',
  30. 'User-Agent' => 'PostmanRuntime/7.15.2'
  31. ));
  32.  
  33. $client->enqueue($request)->send();
  34. $response = $client->getResponse();
  35.  
  36. echo $response->getBody();
  1. <?php
  2. //3、cURL 是一个非常强大的开源库,支持很多协议,包括HTTP、FTP、TELNET等,我们使用它来发送HTTP请求。
    //它给我们带来的好处是可以通过灵活的选项设置不同的HTTP协议参数,并且支持HTTPS。CURL可以根据URL前缀是“HTTP” 还是“HTTPS”自动选择是否加密发送内容。
  3.  
  4. $curl = curl_init();
  5.  
  6. curl_setopt_array($curl, array(
  7. CURLOPT_URL => "http://jszapi.dev.jingjinglego.com/index.php/index/uploadImg",
  8. CURLOPT_RETURNTRANSFER => true,
  9. CURLOPT_ENCODING => "",
  10. CURLOPT_MAXREDIRS => 10,
  11. CURLOPT_TIMEOUT => 30,
  12. CURLOPT_HTTP_VERSION => CURL_HTTP_VERSION_1_1,
  13. CURLOPT_CUSTOMREQUEST => "POST",
  14. 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--",
  15. CURLOPT_HTTPHEADER => array(
  16. "Accept: */*",
  17. "Accept-Encoding: gzip, deflate",
  18. "Cache-Control: no-cache",
  19. "Connection: keep-alive",
  20. "Content-Length: 39091",
  21. "Content-Type: multipart/form-data; boundary=--------------------------296608706222243058746908",
  22. "Host: jszapi.dev.jingjinglego.com",
  23. "Postman-Token: dc010150-b166-4dec-a33f-959a65c91c71,982e059e-bd8b-4db9-83c4-3fd52c8ed82f",
  24. "User-Agent: PostmanRuntime/7.15.2",
  25. "cache-control: no-cache",
  26. "content-type: multipart/form-data; boundary=----WebKitFormBoundary7MA4YWxkTrZu0gW"
  27. ),
  28. ));
  29.  
  30. $response = curl_exec($curl);
  31. $err = curl_error($curl);
  32.  
  33. curl_close($curl);
  34.  
  35. if ($err) {
  36. echo "cURL Error #:" . $err;
  37. } else {
  38. echo $response;
  39. }

  6、如上面3个代码片段,但是后来验证后,发现1/3的参数,不知道是怎么传输的,2的参数很容易看懂,但是运用的话需要开启扩展,这个目前不太合适,所以┭┮﹏┭┮。

二、写在心里

  1、这个上传的问题,确实卡住了,感觉有点难过。其实每次都会遇见一个自己的困难,经常遇见,周末下午的时候,我在家打开电脑,打来远程,准备登陆下ftp拉下代码,发现一直连不上,心里那个烦啊。但是还是通过远程工具(向日葵),将代码拉下来了。想这个图片上传到底怎么弄了,之前也看过,关于通过ftp的方式上传图片,但是后来查看了相关文章需要在php.ini中开启,所以也作罢。

  1. #开启ftp扩展支持
  2. extension=php_ftp.dll

  2、经常遇见困难,经常觉得自己很LOW但是,已经工作了这么久,发现其实问题最后又都解决了,但是现在回想,却忘了到底是怎么解决的,所以写这个博文主要也是想记录下。一直到下午4点多,深圳的天气今年闷热居多,中午我已经昧着良心午休了1个小时,所以现在到现在心里还有些许内疚,唉。

  3、但是还是找不到解决的方法,头疼的厉害,好热。怎么办,我决定靠在椅子上休息下,于是我还是决定躺在沙发上睡会。刚躺下,想着这怎么办呢。

  -----------------------base64---------------------------华丽的分割线

  我突然想到了base64这个读起来,朗朗上口的函数,对如果现将图片转换成base64字符串,再通过POST方式传送给B项目,然后再B项目中对字符串进行解码,生成图片,保存到B项目,然后返回图片路径,不就可以了吗。于是我有推了一遍,发现没有疏忽。于是觉得应该是解决了。

三、解决图片上传问题

  1、A接受web传来图片临时文件,

  1. #上传图片京手指 1:图片保留到本地
  2. public function uploadJszImg()
  3. {$path = config('business.jsz_file_tem');
  4. $file = request()->file('file_upload');
  5. $info = $file->validate(['ext'=>'jpg,jpeg,png,gif'])->move($path);//图片保存到本地
  6. $img_one = $path.$info->getSaveName();//图片路径
  7. $img_base = imgToBase64($img_one);//获取图片base64编码格式
  8. deleteFileWay($path);//删除临时文件
  9. $url = config('business.jsz_api')['baseImg'];
  10. $data = [
  11. 'base_string'=> $img_base,
  12. 'path' => 'upload/goods_img',
  13. ];
  14. $res = http_api($url,$data,1);
  15. $res = json_decode($res,true);
  16. if($res['data']){
  17. $return = ['code'=>1,'message'=>'成功','data'=>'jszapi.dev.jingjinglego.com'.$res['data']];
  18. }else{
  19. $return = ['code'=>0,'message'=>'失败'];
  20. }
  21. return $return;
  22. }

  2、并转换成base64字符串,

  1. /**
  2. * 获取图片的Base64编码(不支持url)
  3. * @param $img_file 传入本地图片地址
  4. * @return string
  5. */
  6. function imgToBase64($img_file) {
  7. $img_base64 = '';
  8. if (file_exists($img_file)) {
  9. $app_img_file = $img_file; // 图片路径
  10. $img_info = getimagesize($app_img_file); // 取得图片的大小,类型等
  11. //echo '<pre>' . print_r($img_info, true) . '</pre><br>';
  12. $fp = fopen($app_img_file, "r"); // 图片是否可读权限
  13. if ($fp) {
  14. $filesize = filesize($app_img_file);
  15. $content = fread($fp, $filesize);
  16. $file_content = chunk_split(base64_encode($content)); // base64编码
  17. switch ($img_info[2]) { //判读图片类型
  18. case 1: $img_type = "gif";
  19. break;
  20. case 2: $img_type = "jpg";
  21. break;
  22. case 3: $img_type = "png";
  23. break;
  24. }
  25. $img_base64 = 'data:image/' . $img_type . ';base64,' . $file_content;//合成图片的base64编码
  26. }
  27. fclose($fp);
  28. }
  29. return $img_base64; //返回图片的base64
  30. }

  3、B接受A项目传来参数

  1. /**
  2. * 将base64字符串转换成图片并保存在本地
  3. * @param Request $request
  4. * @return void
  5. */
  6. public function baseImg(Request $request)
  7. {
  8. $base_string = $request->post('base_string', '');
  9. if (!$base_string) {
  10. $this->apiResult(CustomError::MISSING_PARAMS);
  11. }
  12. $path = $request->post('path', '');
  13. if (!$path) {
  14. $this->apiResult(CustomError::MISSING_PARAMS);
  15. }
  16. $request = base64_image_content($base_string, $path);//解码
  17. if($request){
  18. $this->apiResult(CustomError::OPERATION_SUCCSESS, $request);
  19. }else{
  20. $this->apiResult(CustomError::OPERATION_FAILED);
  21. }
  22. }

  4、对字符解析解码

  1. /**
  2. * [将Base64图片转换为本地图片并保存]
  3. * @param [Base64] $base64_image_content [要保存的Base64]
  4. * @param [目录] $path [要保存的路径]
  5. */
  6. function base64_image_content($base64_image_content,$path){
  7. //匹配出图片的格式
  8. if (preg_match('/^(data:\s*image\/(\w+);base64,)/', $base64_image_content, $result)){
  9. $type = $result[2];
  10. $new_file = $path."/".date('Ymd',time())."/";
  11. if(!file_exists($new_file)){
  12. //检查是否有该文件夹,如果没有就创建,并给予最高权限
  13. mkdir($new_file, 0700);
  14. }
  15. $new_file = $new_file.time().".{$type}";
  16. if (file_put_contents($new_file, base64_decode(str_replace($result[1], '', $base64_image_content)))){
  17. return '/'.$new_file;
  18. }else{
  19. return false;
  20. }
  21. }else{
  22. return false;
  23. }
  24. }

  5、最后返回上传好的图片路径

:结束

PHP代码篇(五)--如何将图片文件上传到另外一台服务上的更多相关文章

  1. PHP文件上传至另一台服务器

    PHP程序上传文件时,想指定上传到另一台服务器. move_uploaded_file这个方法第二个参数指定的存放路径需要和php程序文件一个服务器,没办法指定其他服务器的地址,本人才疏学浅,哪位大哥 ...

  2. ASP.NET工作笔记之一:图片上传预览及无刷新上传

    转自:http://www.cnblogs.com/sibiyellow/archive/2012/04/27/jqueryformjs.html 最近项目里面涉及到无刷新上传图片的功能,其实也就是上 ...

  3. 怎么样通过php使用html5实现多文件上传?(php多图上传)

    <!DOCTYPE html><html lang="zh-cn"> <head> <meta charset="utf-8&q ...

  4. Thinkphp5图片上传正常,音频和视频上传失败的原因及解决

    Thinkphp5图片上传正常,音频和视频上传失败的原因及解决 一.总结 一句话总结:php中默认限制了上传文件的大小为2M,查找错误的时候百度,且根据错误提示来查找错误. 我的实际问题是: 我的表单 ...

  5. PHP-02.文件上传、php保存/转移上传的文件、常见的网络传输协议、请求报文及属性、响应报文及属性

    关系数组 array("key"=>"value",...) ; get没有数据大小的限制 post上传大小没有限制 不指定上传方式,默认是get 文件上 ...

  6. 文件上传和下载(可批量上传)——Spring(三)

    在文件上传和下载(可批量上传)——Spring(二)的基础上,发现了文件下载时,只有在Chrome浏览器下文件名正常显示,还有发布到服务器后,不能上传到指定的文件夹目录,如上传20160310.txt ...

  7. 基于bootstrap的上传插件fileinput实现ajax异步上传功能(支持多文件上传预览拖拽)

    首先需要导入一些js和css文件 ? 1 2 3 4 5 6 <link href="__PUBLIC__/CSS/bootstrap.css" rel="exte ...

  8. jQuery文件上传插件jQuery Upload File 有上传进度条

    jQuery文件上传插件jQuery Upload File 有上传进度条 jQuery文件上传插件jQuery Upload File,插件使用简单,支持单文件和多文件上传,支持文件拖拽上传,有进度 ...

  9. [转]linux将一个服务器上的文件或者文件夹复制到另一台服务器上

    本文转载自<linux 将一个服务器上的文件或者文件夹复制到另一台服务器上>,有时间实践一把 使用scp将一个Linux系统中的文件或文件夹复制到另一台Linux服务器上 复制文件或文件夹 ...

随机推荐

  1. Oracle 备份数据库

    [目录] ①备份数据库(https://www.cnblogs.com/xqz0618/p/oracle_backup.html) ②定时备份数据库(https://www.cnblogs.com/x ...

  2. iptables 从入门到应用

    原创作品,允许转载,转载时请务必以超链接形式标明文章 原始出处 .作者信息和本声明.否则将追究法律责任.http://powermichael.blog.51cto.com/12450987/1952 ...

  3. more than 120 seconds|hung_task_timeout_secs 什么鬼?

    //2019/7/31 18:41:14掐指一算应该resore完了呀,是不是天热想罢工?不过已经差不多30个小时了无意间一查 tail -500f /var/log/messages 发现有些“mo ...

  4. bootrom/spl/uboot/linux逐级加载是如何实现的?

    关键词:bootrom.spl.uboot.linux.mksheader.sb_header.mkimage.image_header_t等等. 首先看一个典型的bootrom->spl-&g ...

  5. webdriver-键盘操作 for java

    2017年01月17日 17:08:25 阅读数:2044 import java.awt.AWTException;import java.awt.Robot;import java.awt.eve ...

  6. 如何解决android 通知栏不显示的问题

    android 8.0 以后的版本,在创建通知栏的时候,加了一个channelId的东西.要想在上述版本中显示通知,总共分两步 1.创建Channel if (Build.VERSION.SDK_IN ...

  7. NOIP 2016 组合数问题

    洛谷 P2822 组合数问题 洛谷传送门 JDOJ 3139: [NOIP2016]组合数问题 D2 T1 JDOJ传送门 Description 组合数Cnm表示的是从n个物品中选出m个物品的方案数 ...

  8. Centos7源码编译安装PHP7.2(生产环境)

    安装PHP依赖包,否则在编译的过程中可能会出现各种报错 # Centos 安装epel-release源并将系统包更新到最新版本 $ yum install epel-release-y $ yum ...

  9. python程序封装成exe流程

    在学习python的过程中,在IDE编写完成py项目,运行成功想要封装成exe,方便分享给不同的人即使别人没有安装python也可以使用. 封装的过程中遇到一些问题,记录一下,方便自己和他人查阅. 以 ...

  10. Eclipse Memory Analyzer(MAT),内存泄漏插件,安装使用一条龙

    网上文档很多,但最初都有问题.整理一份,作为备份.使用过程:开发代码写完后,对可能出现内存溢出的代码,添加配置文件,生成.hprof文件,用memory Analyzer分析排查问题,且泄漏内存大小可 ...