实现原理:通过oss接口下载文件至服务器相关目录,然后进行压缩为一个zip文件,接口调用返回文件流或浏览器访问直接下载文件,下载完成后删除相关目录。
一、ThinkPHP版本6.1
二、PHP版本:8.0
三、逻辑示例代码(根据应用场景更改,主要更改数据来源)
/**
* @notes 下载赛事作品
* @return Json
*/
public function downloadWork(): Json
{
try {
// 设置作品下载或保存目录
$loaclPath = public_path() . '/zip';
// 目录不存在则进行创建
if (!is_dir($loaclPath)) mkdir($loaclPath, 0777, true);
// OSS数据内容,不包含bucket名称
$list = ['1.png','2.png'];
// 定义本地图片数组
$img = [];
foreach ($list as $k => $v) {
// 获取oss文件地址,不包含bucket名称
$object = str_replace('http://myykj-w.oss-cn-hangzhou.aliyuncs.com/', '', $val['down_load_url']);
$filename = '/' . $key . '_文件';
// 文件后缀
$ext = substr($object, stripos($object, '.'));
// 设置文件全名
$fullPath = $loaclPath . $filename . $ext;
$img[] = $fullPath;
// 调用oss下载文件
OssLogic::aliossDownload($object, $fullPath);
}
//这里需要注意该目录是否存在,并且有创建的权限
$fileName = public_path() . '/image.zip';
$zip = new \ZipArchive();
$res = $zip->open($fileName, \ZipArchive::CREATE);
if ($res === TRUE) {
foreach ($img as $file) {
//这里直接用原文件的名字进行打包,也可以直接命名,需要注意如果文件名字一样会导致后面文件覆盖前面的文件,所以建议重新命名
$new_filename = substr($file, strrpos($file, '/') + 1);
$zip->addFile($file, $new_filename);
}
}
//关闭文件
$zip->close();
// 定义下载至本地的文件名称
$downLoadName = '文件.zip';
// 这里是下载zip文件
header("Content-Type: application/zip");
header("Content-Transfer-Encoding: Binary");
header("Content-Length: " . filesize($fileName));
header("Content-Disposition: attachment; filename=\"" . $downLoadName . "\"");
readfile($fileName);
unlink($fileName); // 删除压缩包
deleteDirectory($loaclPath); // 删除文件目录及文件
exit;
} catch (\Exception $e) {
return $this->fail($e->getMessage());
}
}
四、oss下载示例代码(参数需要改为自己oss参数)
/**
* @notes oss下载
* @return bool
*/
public static function aliossDownload($object, $localfile): bool
{
// 从环境变量中获取访问凭证。运行本代码示例之前,请确保已设置环境变量OSS_ACCESS_KEY_ID和OSS_ACCESS_KEY_SECRET。
$accessKeyId = config('AccessKeyId');
$accessKeySecret = config('AccessKeySecret');
// Endpoint以杭州为例,其它Region请按实际情况填写。
$endpoint = config('Endpoint');
// 设置存储空间名称。
$bucket = config('Bucket');
//下载地址
$options = array(
OssClient::OSS_FILE_DOWNLOAD => $localfile
);
// 使用try catch捕获异常。如果捕获到异常,则说明下载失败;如果没有捕获到异常,则说明下载成功。
try {
$ossClient = new OssClient($accessKeyId, $accessKeySecret, $endpoint);
$ossClient->getObject($bucket, $object, $options);
return true;
} catch (OssException $e) {
printf(__FUNCTION__ . ": FAILED\n");
printf($e->getMessage() . "\n");
return false;
}
}
五、删除目录示例代码
/**
* @notes 递归删除文件夹
* @return true
*/
function deleteDirectory($dir): bool
{
if (!is_dir($dir)) {
return false;
}
$files = array_diff(scandir($dir), array('.', '..'));
foreach ($files as $file) {
(is_dir("$dir/$file")) ? deleteDirectory("$dir/$file") : unlink("$dir/$file");
}
return rmdir($dir);
}