项目中,有一需求:为保证对方数据安全,并禁止下载,对方指定网址指定端口号,并对其访问设置白名单,通过一定规则访问到内部资源数据,访问成功则返回文件流。
对返回的文件流,进行保存,并存入数据库,以便后续使用。
起初我并未处理过文件流,就使用 file_get_contents 和 file_put_contents 进行处理,但得不到结果。后续查阅函数发现 stream_copy_to_stream() 这个函数。专门对数据流进行复制保存。
//源文件
$url = 'http://ip:port';
//资源替换规则
$var = '/home/img?p=thumbs';
$prefix = 'source_';
//目标保存目录
$dest_dir = '/dev/resource_center/';
//处理数据
$data = [
'high' => 'high_pict',
'big' => 'big_pict',
'small' => 'small_pict'
];
$fields = implode(',', array_map(function($v) use ($prefix) {return $prefix.$v;},$data));
$sql = 'select ' . $fields . ' from books ………………';
//$res 为 sql 查询结果
foreach ($res as $key => $value) {
//执行替换
$source = str_replace('/pro/upload', $url . $var, $value);
$data_key = array_search(substr($key,strlen($prefix)), $data);
//访问源文件,调用函数进行流的复制保存
$copy_res = copy_file($source, $dest_dir . $data_key);
var_dump($copy_res);
}
/**
* 流的复制保存
* @param source 必选 string 源文件路径
* @param dest 必选 string 目标保存路径
* @return boolean|string 失败:false|成功:目标文件路径
*/
function copy_file($source, $dest) {
is_dir($dest) || mkdir($dest, 0777, true);
$dest = $dest . '/' . basename($source);
try {
$fsource = fopen($source, 'r');
$fdest = fopen($dest, 'w+');
//流的复制保存
$res = stream_copy_to_stream($fsource, $fdest);
fclose($fsource);
fclose($fdest);
if (false === $res) {
throw new Exception('Error Fail');
}
} catch (\Exception $e) {
return ['errno' => 1, 'msg' => $e->getMessage()];
}
return ['errno' => 0, 'msg' => $dest];
}