jszip 官网
思路
- 服务器接口返回资源路径获取资源内容(资源内容引用了资源,需更改内容的引用路径为相对路径);
- 前端项目安装
jszip依赖;
- 使用依赖导出
zip文件
后端接口
/**
* 获取反转资源url
* @param string $initAssetsUrl
* @param $assets
* @return string
*/
private function getAssetsReversalUrl(string $initAssetsUrl, $assets) {
$assetsDirName = 'index_files';
$assetsUrl = $initAssetsUrl;
$assetsNameArr = explode('/', $initAssetsUrl);
$assetsName = end($assetsNameArr);
if (!empty($assets[$assetsName])) {
$assetsUrl = $assetsDirName . '/' . $assetsName;
}
return $assetsUrl;
}
/**
* 导出
* @param int $newsId
* @return array|bool|string
*/
public function export(int $newsId)
{
$detail = NewsModel::detail($newsId);
if (empty($detail)) return $this -> renderError('新闻不存在');
$detail = $detail -> toArray();
$destinationFile = ($detail['suffix'] ?: $detail['id']) . '.zip';
$assetsArr = json_decode($detail['assets'], true);
$assets = [];
$assetsMap = [];
foreach ($assetsArr as $item) {
$filePath = $item['file_path'];
$filePathArr = explode('/', $filePath);
$filePathName = end($filePathArr);
$assets[$filePathName] = $item;
$item['domain'] = Env::get('OSS_CUSTOM_DOMAIN');
$item['file_path_name'] = $filePathName;
$assetsMap[] = $item;
}
$fileContent = $detail['html_content'];
$assetsDirName = 'index_files';
$domain = request() -> domain();
// 还原html,资源改为相对路径
$fileContent = preg_replace_callback_array(
[
'/<link([^>]*)href="([^"]+)"([^>]*)>/si' => function ($matches) use ($assets) {
// 这里可以添加逻辑来处理 $matches[2](原始值)
$assetsUrl = $this -> getAssetsReversalUrl($matches[2], $assets);
return "<link{$matches[1]}href=\"{$assetsUrl}\"{$matches[3]}>";
},
'/<script([^>]*)src="([^"]+)"([^>]*)>(.*?)<\/script>/si' => function ($matches) use ($assets) {
// 这里可以添加逻辑来处理 $matches[2](原始值)
$assetsUrl = $this -> getAssetsReversalUrl($matches[2], $assets);
return "<script{$matches[1]}href=\"{$assetsUrl}\"{$matches[3]}>{$matches[4]}</script>";
},
'/<img([^>]*)[^\-]src="([^"]+)"([^>]*)>/si' => function ($matches) use ($assets) {
// 这里可以添加逻辑来处理 $matches[2](原始值)
$assetsUrl = $this -> getAssetsReversalUrl($matches[2], $assets);
return "<img{$matches[1]} src=\"{$assetsUrl}\"{$matches[3]}>";
},
'/<video[^>]*src="([^"]+)"([^>]*)>(.*?)<\/video>/si' => function ($matches) use ($assets) {
// 这里可以添加逻辑来处理 $matches[2](原始值)
$assetsUrl = $this -> getAssetsReversalUrl($matches[2], $assets);
return "<video{$matches[1]}href=\"{$assetsUrl}\"{$matches[3]}>{$matches[4]}</video>";
},
'/<audio[^>]*src="([^"]+)"([^>]*)>(.*?)<\/audio>/si' => function ($matches) use ($assets) {
// 这里可以添加逻辑来处理 $matches[2](原始值)
$assetsUrl = $this -> getAssetsReversalUrl($matches[2], $assets);
return "<audio{$matches[1]}href=\"{$assetsUrl}\"{$matches[3]}>{$matches[4]}</audio>";
},
'/<source[^>]*src="([^"]+)"([^>]*)>/si' => function ($matches) use ($assets) {
// 这里可以添加逻辑来处理 $matches[2](原始值)
$assetsUrl = $this -> getAssetsReversalUrl($matches[2], $assets);
return "<source{$matches[1]}href=\"{$assetsUrl}\"{$matches[3]}>";
},
'/<track[^>]*src="([^"]+)"([^>]*)>/si' => function ($matches) use ($assets) {
// 这里可以添加逻辑来处理 $matches[2](原始值)
$assetsUrl = $this -> getAssetsReversalUrl($matches[2], $assets);
return "<track{$matches[1]}href=\"{$assetsUrl}\"{$matches[3]}>";
},
'/<embed([^>]*)src="([^"]+)"([^>]*)>/si' => function ($matches) use ($assets) {
// 这里可以添加逻辑来处理 $matches[2](原始值)
$assetsUrl = $this -> getAssetsReversalUrl($matches[2], $assets);
return "<embed{$matches[1]}href=\"{$assetsUrl}\"{$matches[3]}>";
},
'/<iframe([^>]*)src="([^"]+)"([^>]*)>(.*?)<\/iframe>/si' => function ($matches) use ($assets) {
// 这里可以添加逻辑来处理 $matches[2](原始值)
$assetsUrl = $this -> getAssetsReversalUrl($matches[2], $assets);
return "<iframe{$matches[1]}href=\"{$assetsUrl}\"{$matches[3]}>{$matches[4]}</iframe>";
},
],
$fileContent
);
$detail['assets'] = $assetsMap;
$detail['assets_dir_name'] = $assetsDirName;
$detail['cur_domain'] = $domain;
$detail['html_content'] = $fileContent;
$detail['file_name'] = $destinationFile;
return $this->renderSuccess($detail, '查询成功');
}