說,我有一個需求,就是一個臨時功能。由于工作開發(fā)問題,我們有一個B項目,需要有一個商品添加的功能,涉及到添加商品內(nèi)容,比如商品名字,商品描述,商品庫存,商品圖片等。后臺商品添加的接口已經(jīng)寫完了,但是問題是目前沒有后臺頁面,就是產(chǎn)品還沒有出后臺詳細(xì)頁面。前端已經(jīng)完備了,上線了。后臺還需要工作時間處理。所以目前的處理方法是在我們已經(jīng)存在的A項目后臺中,添加一個對B項目添加商品的功能。
![](/d/20211017/a3a4d548bb8c31fc18463de82ebf04bc.gif)
一、當(dāng)下問題
1、在我們已有的A項目中,新增一個添加商品的功能,這個本來是沒有什么問題的,因為目前A項目中本身就已經(jīng)連接了B項目的數(shù)據(jù)庫,所以商品屬性的新增和修改都沒什么問題。主要是商品圖片的上傳這里,有點問題。B項目已經(jīng)對外提供了上傳圖片的接口,但是由于我確實對前端不是特別熟悉。所以在A項目中的后臺JS中調(diào)取B項目的上傳圖片的接口時,一直提示"CORS",這里應(yīng)該是存在一個跨域的問題,雖然我PHP接口端已經(jīng)對跨域做了處理(入口文件處),但是貌似JS這邊也需要相應(yīng)的調(diào)整。
![](/d/20211017/e5edbe89f4ab86901f11c4721d0ced17.gif)
// [ 應(yīng)用入口文件 ]
//入口文件index.php
namespace think;
// 加載基礎(chǔ)文件
require __DIR__ . '/thinkphp/base.php';
// 支持事先使用靜態(tài)方法設(shè)置Request對象和Config對象
header("Access-Control-Allow-Origin: *");
header("Access-Control-Allow-Headers: Content-Type,XFILENAME,XFILECATEGORY,XFILESIZE,authorization");
// 執(zhí)行應(yīng)用并響應(yīng)
Container::get('app')->bind('api')->run()->send();
2、無奈小白JS功底不夠扎實,所以我這邊準(zhǔn)備通過A項目中調(diào)取后臺PHP接口,然后通過在PHP代碼中接受web端參數(shù),然后再轉(zhuǎn)發(fā),調(diào)取B項目中上傳圖片的接口,試圖完成功能。于是先通過Postman接口工具測試了一下B項目上傳圖片的接口是否有效。如圖3,發(fā)現(xiàn)確實沒有什么問題,于是就準(zhǔn)備如此處理。
![](/d/20211017/4cb75c99748f745f01953afaf1dbe1d6.gif)
3、但是實際是,在調(diào)取時,我們常用的傳參數(shù)方式是GET或者POST方式,但是我們知道文件上傳是通過$_FILES接受,下面是B項目的上傳圖片的控制器代碼(用的是TP5.1),接受是通過內(nèi)置的file方式。
/**上傳圖片
* @param Request $request
*/
public function uploadImg(Request $request){
$file = $request->file('image');
$type = $request->post('type', 0);
// 移動到框架應(yīng)用根目錄/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、所以在轉(zhuǎn)發(fā)A項目web端傳來的,文件內(nèi)容,就有點不知所措了。該死,該死。
//文件上傳接受參數(shù)
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、所以按剛才設(shè)想的,簡單做下轉(zhuǎn)發(fā)還是不行,這里面參數(shù)的傳輸方式應(yīng)該還有另外一種,就是文件的類型。鑒于是通過Postman方式上傳成功,這個工具確實很推薦多多學(xué)習(xí),他不僅作為一個第三方中間為我們驗證接口是否可用,更給我們提供了調(diào)取接口的各種代碼Damo,如圖3中標(biāo)識的Code處,就是獲取Damo的按鈕。我們點擊可以看見Postman給我提供了三種,調(diào)取接口的方式。
?php
//1、HttpRequest 發(fā)送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 擴(kuò)展
$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/網(wǎng)站圖標(biāo)/網(wǎng)站素材/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 是一個非常強(qiáng)大的開源庫,支持很多協(xié)議,包括HTTP、FTP、TELNET等,我們使用它來發(fā)送HTTP請求。//它給我們帶來的好處是可以通過靈活的選項設(shè)置不同的HTTP協(xié)議參數(shù),并且支持HTTPS。CURL可以根據(jù)URL前綴是“HTTP” 還是“HTTPS”自動選擇是否加密發(fā)送內(nèi)容。
$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個代碼片段,但是后來驗證后,發(fā)現(xiàn)1/3的參數(shù),不知道是怎么傳輸?shù)模?的參數(shù)很容易看懂,但是運用的話需要開啟擴(kuò)展,這個目前不太合適,所以┭┮﹏┭┮。
二、寫在心里
1、這個上傳的問題,確實卡住了,感覺有點難過。其實每次都會遇見一個自己的困難,經(jīng)常遇見,周末下午的時候,我在家打開電腦,打來遠(yuǎn)程,準(zhǔn)備登陸下ftp拉下代碼,發(fā)現(xiàn)一直連不上,心里那個煩啊。但是還是通過遠(yuǎn)程工具(向日葵),將代碼拉下來了。想這個圖片上傳到底怎么弄了,之前也看過,關(guān)于通過ftp的方式上傳圖片,但是后來查看了相關(guān)文章需要在php.ini中開啟,所以也作罷。
#開啟ftp擴(kuò)展支持
extension=php_ftp.dll
2、經(jīng)常遇見困難,經(jīng)常覺得自己很LOW但是,已經(jīng)工作了這么久,發(fā)現(xiàn)其實問題最后又都解決了,但是現(xiàn)在回想,卻忘了到底是怎么解決的,所以寫這個博文主要也是想記錄下。一直到下午4點多,深圳的天氣今年悶熱居多,中午我已經(jīng)昧著良心午休了1個小時,所以現(xiàn)在到現(xiàn)在心里還有些許內(nèi)疚,唉。
3、但是還是找不到解決的方法,頭疼的厲害,好熱。怎么辦,我決定靠在椅子上休息下,于是我還是決定躺在沙發(fā)上睡會。剛躺下,想著這怎么辦呢。
-----------------------base64---------------------------華麗的分割線
我突然想到了base64這個讀起來,朗朗上口的函數(shù),對如果現(xiàn)將圖片轉(zhuǎn)換成base64字符串,再通過POST方式傳送給B項目,然后再B項目中對字符串進(jìn)行解碼,生成圖片,保存到B項目,然后返回圖片路徑,不就可以了嗎。于是我有推了一遍,發(fā)現(xiàn)沒有疏忽。于是覺得應(yīng)該是解決了。
![](/d/20211017/633be0dfc214322b845a86f95a63df29.gif)
三、解決圖片上傳問題
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、并轉(zhuǎn)換成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"); // 圖片是否可讀權(quán)限
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項目傳來參數(shù)
/**
* 將base64字符串轉(zhuǎn)換成圖片并保存在本地
* @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圖片轉(zhuǎn)換為本地圖片并保存]
* @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)){
//檢查是否有該文件夾,如果沒有就創(chuàng)建,并給予最高權(quán)限
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、最后返回上傳好的圖片路徑
:結(jié)束
總結(jié)
以上所述是小編給大家介紹的PHP如何將圖片文件上傳到另外一臺服務(wù)器上,希望對大家有所幫助,如果大家有任何疑問請給我留言,小編會及時回復(fù)大家的。在此也非常感謝大家對腳本之家網(wǎng)站的支持!
如果你覺得本文對你有幫助,歡迎轉(zhuǎn)載,煩請注明出處,謝謝!
您可能感興趣的文章:- PHP5.4起內(nèi)置web服務(wù)器使用方法
- phpstorm遠(yuǎn)程連接服務(wù)器并實時更新發(fā)布代碼(thinkphp6.0.7)
- PhpStorm連接服務(wù)器并實現(xiàn)自動上傳功能
- PHP使用swoole編寫簡單的echo服務(wù)器示例
- php實現(xiàn)的簡單多進(jìn)程服務(wù)器類完整示例
- 在phpstudy集成環(huán)境下的nginx服務(wù)器下配置url重寫
- php服務(wù)器的系統(tǒng)詳解
- Windows服務(wù)器中PHP如何安裝redis擴(kuò)展
- 微信小程序上傳圖片到php服務(wù)器的方法
- PHP 內(nèi)置WEB服務(wù)器的簡單使用