照例先说一下背景,即接收上传音频文件,转码为mp3后,通过curl上传至目标服务器中。
接收文件:
/**
* @Notes:接收文件
* @Interface getFile
* @param Request $request
* @return \think\response\Json
*/
public function getFile(Request $request){
//上传文件保存地址
$upload_dir = '../uploads';
//转码后保存地址
$target_dir = '../uploads';
//提交目标url
$target_url = '';
$data = $request->param();
$file = $request->file('upload_file');
//判断文件是否存在
if(!$file || $file ==''){
// 上传失败获取错误信息
$return_data = [];
$return_data['status'] = 0;
$return_data['msg'] = '没有获取到文件';
$return_data['data'] = [];
return json($return_data);
}else{
// 移动到框架应用根目录/uploads/ 目录下
//此处这种写法为保留原文件名,否则去掉第二个参数即可
//$info = $file->move( $upload_url);
$info = $file->move( $upload_dir,'');
//判断结果
if($info){
$upload_file_url = $upload_dir."/".$info->getFilename();
$target_file_url = $target_dir."/".$info->getFilename().".mp3";
$res_command = $this->fileProcess($upload_file_url,$target_file_url);
//判断文件是否转码成功,即判断转码文件是否存在,
//若转码需要时间,可以循环获取,获取锁失败则重试{$num}次
$num = 5;
for($i=0; $i<$num; $i++){
if(file_exists(realpath($target_file_url))){
break;
}
sleep(1);
}
if(file_exists(realpath($target_file_url))){
//删除上传文件
@unlink($upload_file_url);
//将文件传送到指定地址
$this->putFile($target_url,$target_file_url,$data);
}
}else{
$return_data = [];
$return_data['status'] = 0;
$return_data['msg'] = '文件移动失败';
$return_data['data'] = [];
return json($return_data);
}
}
}
文件转码:
/**
* @Notes:文件转码
* @Interface fileProcess
* @param $url
* @param $target_url
* @return string
*/
public function fileProcess($url,$target_url){
$command = "/usr/bin/ffmpeg -i {$url} {$target_url}";
$res_command = exec($command,$error);
return $res_command;
}
传送文件:
/**
* @Notes:传送文件
* @Interface putFile
* @param $target_url
* @param $file_url
* @param $data
* @return array|bool|string
*/
public function putFile($target_url,$file_url,$data){
// 初始化 cURL 会话, 如果提供url,CURLOPT_URL 选项将会被设置成这个值
$ch = curl_init($target_url);
// 获取CURLFile实例
$dataCurlFile = $this->makeCurlFile(realpath($file_url));
$data['upload_file'] = $dataCurlFile;
//参数设置,是否显示头部信息,1为显示,0为不显示
curl_setopt($ch, CURLOPT_HEADER, 0);
curl_setopt($ch, CURLINFO_HEADER_OUT, 1);
//设置为true可获取返回值
curl_setopt($ch, CURLOPT_RETURNTRANSFER, 1);
// TRUE 时会发送 POST 请求
curl_setopt($ch, CURLOPT_POST, 1);
// 从 PHP 5.5.0 开始, @ 前缀已被废弃,文件可通过 CURLFile 发送。
// 设置 CURLOPT_SAFE_UPLOAD 为 TRUE 可禁用 @ 前缀发送文件,以增加安全性。
curl_setopt($ch, CURLOPT_CONNECTTIMEOUT, 5);
// 重要, 该处不能丢 curl 执行最大秒数
curl_setopt($ch, CURLOPT_TIMEOUT, 10);
//提供数据
curl_setopt($ch, CURLOPT_POSTFIELDS, $data);
// 执行给定的 cURL 会话
// 成功时返回 TRUE, 或者在失败时返回 FALSE。
//如果 设置了 CURLOPT_RETURNTRANSFER 选项,函数执行成功时会返回执行的结果,失败时返回 FALSE 。
//返回错误信息,或者如果没有任何错误发生就返回 '' (空字符串)
$result = curl_exec($ch);
//获取代码 返回错误代码或在没有错误发生时返回 0 (零)。
$error_no = curl_errno($ch);
// 关闭 cURL 会话
curl_close($ch);
//删除文件
$return_data = [];
if($result === false){
//$error_no错误码7为连接不上,28为连接上了但请求返回结果超时
if($error_no == 7){
$return_data['msg'] = '连接失败';
}elseif ($error_no == 28){
$return_data['msg'] = '返回结果超时';
}else{
$return_data['msg'] = '操作失败';
}
$return_data['status'] = 0;
$return_data['data'] = $result;
}else{
//删除文件
@unlink($file_url);
$return_data['status'] = 1;
$return_data['msg'] = '操作成功';
$return_data['data'] = $data;
}
return $return_data;
}
private function makeCurlFile($file)
{
/**
* .mp3 mime为 audio/mpeg
* .png mime为 image/png
* 可参考 https://developer.mozilla.org/zh- CN/docs/Web/HTTP/Basics_of_HTTP/MIME_types/Complete_list_of_MIME_types
*
* 注意:也可以使用 finfo类动态获取,但需要装fileinfo扩展
* demo:
$result = new finfo();
if (is_resource($result) === true) {
return $result->file($filename, FILEINFO_MIME_TYPE);
}
return false;
*/
$mime = "audio/mpeg";
$info = pathinfo($file);
$name = $info['basename'];
$output = new \CURLFile($file, $mime, $name);
return $output;
}