前言:项目中存在本地服务器图片和阿里oss图片,需要将信息导出,并下载,oss下载到本地太占信息,所以拷贝到一个oss到一个地址,然后告诉用户地址,在将这个文件夹下载,路径要和导入的excel文件中的url地址相匹配,本地服务器的文件,则直接打包到这个zip包中,下载。
`php
public function package(Request $request)
{
if($request->isPost())
{
# 前台发送过来的请求信息
/*
* filename 文件名 可为空,如果不为空则以这个为文件名
* eid 赛事id
* lunci 要打包的轮次
* */
$data = $request->param('');
$eid = $data['eid'];
$filename_zip = $data['filename'];
$lunci = $data['lunci'];
# 我的数据逻辑操作
switch($lunci){
case 1:
$zu_id = 'zu_id1';
break;
# 如果是第二轮的时候,需要判断当前轮数,第一次是否存在,如果存在可以继续向下执行,否则不允许执行。
case 2:
$zu_id = 'zu_id2';
break;
case 3:
$zu_id = 'zu_id3';
break;
case 4:
$zu_id = 'zu_id4';
break;
case 5:
$zu_id = 'zu_id5';
break;
case 6:
$zu_id = 'zu_id6';
break;
case 7:
$zu_id = 'zu_id7';
break;
case 8:
$zu_id = 'zu_id8';
break;
case 9:
$zu_id = 'zu_id9';
break;
case 0: # 所有图片 和得奖人员,到时候在做判断
default:
$zu_id = 0;
break;
}
# 判断当前是下载所有图片还是 得奖作品 或者那个轮次的
if($lunci == 0)
{
$where = ['m.events_id' => $eid];
$res = \app\admin\model\Multipe::downfile($where);
}else if($lunci >= 0)
{
$where = ['m.awards' => ['>',0],'m.events_id' => $eid];
$res = \app\admin\model\Multipe::downfile($where);
}else{
$where = ["m.{$zu_id}" => ['>',0],'m.events_id' => $eid];
$res = \app\admin\model\Multipe::downfile($where);
}
# 判断是否为空
if(empty($res))
{
echo "<script>
alert('没有此信息');
wk.layer_close();
</script>";
die;
}
# 赛事名称
$events = \app\admin\model\Events::where('id',$eid)->field('eventsname')->find();
# 以赛事名称创建 表格文件
$title = $events['eventsname'];
# 转码
urlencode($title);
urldecode($title);
// 随机生成的文件名
$fileName = $title.'.xls';
# 引入phpexcel类文件
vendor("PHPExcel.PHPExcel.PHPExcel");
vendor("PHPExcel.PHPExcel.IOFactory");
//加载第三方类库
//实例化excel类
$excelObj = new PHPExcel;
//构建列数--根据实际需要构建即可
$letter = array('A', 'B', 'C', 'D','E','F','G','H','I','J','K','L','M','N','O','P');
//表头数组--需和列数一致
$tableheader = array('赛事名称', '作者姓名', '作品分数','分类A','分类B','是否得奖','作品名称','单服或者多副','作品内容','手机号','email','详细地址','作品添加时间','性别','团体码', '作品图片');
# 设置表头
for($i = 0;$i < count($tableheader);$i++) {
$excelObj->getActiveSheet()->setCellValue("$letter[$i]1","$tableheader[$i]");
}
# 传递数据
for ($i = 2;$i <= count($res) + 1;$i++) {
$j = 0;
foreach ($res[$i - 2] as $key=>$value) {
$excelObj->getActiveSheet()->setCellValue("$letter[$j]$i",urldecode("$value"));
$j++;
}
}
# 创建execel
$write = PHPExcel_IOFactory::createWriter($excelObj, 'Excel5');
# 命名
$_fileName = iconv("utf-8", "gbk", $fileName); //转码
# 文件路径
$_savePath = ROOT_PATH.'public/'.$_fileName;
# 保存到改路径中
$write->save($_savePath);
# 直接下载
# $write->save("php//output");
# 打包下载 这个是我编写的图片路径
$img_src = [];
foreach($res as &$v)
{
$img_src[]['img_src'] = explode(',',urldecode($v['img_src']));
unset($v['img_src']);
}
foreach($img_src as $v)
{
foreach($v['img_src'] as $value)
{
# 在前面携带 前缀 如果是oss则代表我数据库 存储的文件是阿里云oss文件. 需要拷贝文件
# $value = 路径 表示是oss服务器上代码
if(substr($value,0,3) == 'oss')
{
# 如果不等于则 在oss上移动 文件 置顶路径添加oss用来区分是本地服务器和线上服务器的。
# $file_oss[] = $value; // 原本是想要直接下载到本地的,但是现在不需要了,可以关闭
$accessKeyId = config('alyoss.accessKeyId');//去阿里云后台获取秘钥
$accessKeySecret = config('alyoss.accessKeySecret');//去阿里云后台获取秘钥
$endpoint = config('alyoss.endpoint');//你的阿里云OSS地址
$from_bucket = "ss-cwpanet-1"; # 当前文件的bucket
$to_bucket = "ss-cwpanet-1"; # 要移动的 桶
# 本身数据库存储的是upload但我经过处理 区分调整成oss 所以替换一下,不然 oss会找不到这个key报错
$ybstr = substr($value,5,strlen($value));
# 解码,我在模型中进行编码了,因为在刚使用oss 的时候 没有进行编码转换,所以现在必须要进行 转码。 悔不当初哇, 平白无故的添加bug
$from_object = urldecode($ybstr); # 要移动的文件名
# 修改的文件名 则是当前保存的文件名,
$to_object = urldecode($value); # 修改的文件名
# 阿里云复制文件 可以直接copy一份到oss中
try{
$ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint);
# b拷贝命令
$ossClient->copyObject($from_bucket, $from_object, $to_bucket, $to_object);
} catch(OssException $e) {
printf(__FUNCTION__ . ": FAILED\n");
printf($e->getMessage() . "\n");
continue; # continue是精髓 如果是break语句则回直接终止,单我们导出的信息就无法报错,所以 使用continue终止本次循环,然后做个记录就可以了
}
}else{
# 获取本地的文件 我的图片分为当前服务器和oss两个地方存储,所以本地的可以直接打个压缩包下载,所以需要保存路径,然后通过打包下载
$fileList[] = ROOT_PATH.'public'.$value;
}
}
}
$zip = new \ZipArchive; // 实例化zip对象
$zip_time = empty($filename_zip) ? time().".zip" : $filename_zip.'.zip'; // 压缩的目录名
$zip_filename = ROOT_PATH."public/uploads/".$zip_time; // 指定一个压缩包地址
# 打开这个zip包,如果没有则创建
$zip->open($zip_filename,\ZipArchive::CREATE); //打开压缩包 如果没有则 创建
# 判断如果本地文件是空的可以不执行这个,
if(!empty($fileList))
{
# 对这个对象进行循环遍历,
foreach($fileList as $file){
$str = strstr($file,"uploads");
urldecode($str);
$zip->addFile($file,$str); //向压缩包中添加文件
}
}
# 将导出的excel文件追加到这个压缩包中
$zip->addFile($_savePath,$fileName);
# 关闭zip 包
$zip->close();
echo '文件打包成功,请千万public/uploads/目录下查看信息';
die;
# 到这里是下载,但是有问题,很神奇的是,每次执行的都是到128mb就中断执行了,下载不了,很气愤
# 不能使用暂时关闭
header("Content-type:text/html;charset=utf-8");
$file_name = iconv("utf-8","gb2312",$zip_time);
# 将反斜杠 替换成正斜杠
$file_path = str_replace('\\','/',$zip_filename);
if(!file_exists($file_path)){
echo "下载文件不存在!";exit;
}
$file_size=filesize($file_path);
//下载文件需要用到的头
Header("Content-type: application/octet-stream");
Header("Accept-Ranges: bytes");
Header("Accept-Length:".$file_size);
Header("Content-Disposition: attachment; filename = ". $file_name);
$buffer=4096;
$file_count=0;
$fp=fopen($file_path,"rb");
while(!feof($fp) && $file_count<$file_size){
$file_con=fread($fp,$buffer);
$file_count+=$buffer;
echo $file_con;
}
fclose($fp); //关闭这个打开的文件
unlink($_savePath); # 因为是将excel打包进入到了zip包,所以到这一步可以删除文件,节省硬盘容量。
die;
}
$eid = $request->param('eid');
$this->assign('eid',$eid);
return $this->fetch('/events/package');
}
`