运营想快速发布新闻,通过浏览器找到较好的新闻内容页,他们将网页保存下来(Ctrl + S)。下载后的内容基本是index.html文件+index_files文件夹。
他们想将这资源快速上传到我们自有网站上,上传同时指定所有链接跳转到他们指定的url页面。然后生产我们自己的新闻详情链接,复制链接去各大平台推广。
用户上传压缩index.html文件+index_files文件夹的zip文件,服务端将压缩文件保存到指定目录,然后读取压缩文件的index.html文件,将所有a标签链接替换成自定义url,最后解压到指定目录下。
如果才是分布式部署,此方法无效,因为资源上传是到某个服务器上。如果用户访问的是其他服务器,那么资源链接将会读取失败,不能正常打开。
php 7.1+ php扩展库:zip 框架: tp6
前端使用react/vue + antd UI组件都行,只要实现zip文件上传和目标url输入框即可。
/**
* 添加文章
* @return array|mixed
*/
public function add()
{
// 新增记录
$model = new NewsModel;
// 表单提交参数
$params = request() ->post();
// 获取表单上传文件
$file = request()->file('file');
// 文件校验
$FileValidate = new FileValidate;
if (!$FileValidate->check(['file_zip' => $file])) return $this->renderError($FileValidate->getError() ?: '添加失败');
// 上传压缩文件至本地
$savename = Filesystem::disk('news') -> putFile("", $file);
$suffix = $file -> extension(); // 获取文件后缀
$pattern = '/(.*)\/(.*)\.'.$suffix.'/';
preg_match($pattern, $savename, $matches);
$pathPre = $matches[1]; // 文件路径前半段
$name = $matches[2]; // 文件名称,不含后缀
$newsPath = 'news/'; // 保存路径前缀
$savePath = $newsPath . $savename; // 上传后文件路径
$zip = new ZipArchive();
$res = $zip->open($savePath, ZipArchive::CREATE);
if ($res !== TRUE) return $this->renderError('添加失败,解压失败,请稍后重试');
$taegetPath = $newsPath . $pathPre . '/' . $name; // 最终的目标文件夹路径
$fileName = 'index.html';
if (!empty($params['target_url'])) {
if ($zip->locateName($fileName) === false) return $this->renderError("文件 '$fileName' 在ZIP文件中未找到。");
// 获取文件内容
$fileContent = $zip->getFromName($fileName);
// 修改文件内容 替换全局a标签href的值
$newContent = preg_replace_callback(
'/<a\s[^>]*href="([^"]+)"[^>]*>(.*?)<\/a>/si',
function ($matches) use ($params) {
// 这里可以添加逻辑来处理 $matches[1](原始href值)
$newHref = $params['target_url'];
return "<a href=\"{$newHref}\">{$matches[2]}</a>";
},
$fileContent
);
$zip->addFromString($fileName, $newContent);
if ($zip->status != ZipArchive::ER_OK) return $this->renderError('写入错误,' . $zip->getStatusString());
$zip->close();
// 解压文件
$zipNew = new ZipArchive();
$res = $zipNew->open($newsPath . $savename, ZipArchive::CREATE);
if ($res !== TRUE) return $this->renderError("文件 '$fileName' 在ZIP文件中未找到。");
$zipNew->extractTo($taegetPath);
$zipNew->close();
} else {
$zip->extractTo($taegetPath);
$zip->close();
}
$postParam = [
'title' => $params['title'],
'old_name' => $params['old_name'],
'zip_url' => $savePath,
'save_dir' => $taegetPath,
'page_url' => $taegetPath . '/' . $fileName,
'sort' => $params['sort'],
'status' => $params['status'],
'target_url' => $params['target_url'] ?? '',
];
if ($model->add($postParam)) {
return $this->renderSuccess('添加成功');
}
return $this->renderError($model->getError() ?: '添加失败');
}
/**
* 更新文章
* @param int $newsId
* @return array|mixed
*/
public function edit(int $newsId)
{
// 文章详情
$model = NewsModel::detail($newsId);
// 表单提交参数
$params = request() ->post();
$postParam = [
'title' => $params['title'],
'sort' => $params['sort'],
'status' => $params['status'],
'target_url' => $params['target_url'] ?? '',
];
// 获取表单上传文件
$file = request()->file('file');
if (!empty($file)) {
// 有修改文件
// 文件校验
$FileValidate = new FileValidate;
if (!$FileValidate->check(['file_zip' => $file])) return $this->renderError($FileValidate->getError() ?: '添加失败');
// 上传压缩文件至本地
$savename = Filesystem::disk('news') -> putFile( "", $file);
$suffix = $file -> extension(); // 获取文件后缀
$pattern = '/(.*)\/(.*)\.'.$suffix.'/';
preg_match($pattern, $savename, $matches);
$pathPre = $matches[1]; // 文件路径前半段
$name = $matches[2]; // 文件名称,不含后缀
$newsPath = 'news/'; // 保存路径前缀
$savePath = $newsPath . $savename; // 上传后文件路径
$zip = new ZipArchive();
$res = $zip->open($savePath, ZipArchive::CREATE);
if ($res !== TRUE) return $this->renderError('添加失败,解压失败,请稍后重试');
$taegetPath = $newsPath . $pathPre . '/' . $name; // 最终的目标文件夹路径
$fileName = 'index.html';
if (!empty($params['target_url'])) {
if ($zip->locateName($fileName) === false) return $this->renderError("文件 '$fileName' 在ZIP文件中未找到。");
// 获取文件内容
$fileContent = $zip->getFromName($fileName);
// 修改文件内容 替换全局a标签href的值
$newContent = preg_replace_callback(
'/<a\s[^>]*href="([^"]+)"[^>]*>(.*?)<\/a>/si',
function ($matches) use ($params) {
// 这里可以添加逻辑来处理 $matches[1](原始href值)
$newHref = $params['target_url'];
return "<a href=\"{$newHref}\">{$matches[2]}</a>";
},
$fileContent
);
$zip->addFromString($fileName, $newContent);
if ($zip->status != ZipArchive::ER_OK) return $this->renderError('写入错误,' . $zip->getStatusString());
$zip->close();
// 解压文件
$zipNew = new ZipArchive();
$res = $zipNew->open($newsPath . $savename, ZipArchive::CREATE);
if ($res !== TRUE) return $this->renderError("文件 '$fileName' 在ZIP文件中未找到。");
$zipNew->extractTo($taegetPath);
$zipNew->close();
} else {
$zip->extractTo($taegetPath);
$zip->close();
}
$postParam['old_name'] = $params['old_name'];
$postParam['zip_url'] = $savePath;
$postParam['save_dir'] = $taegetPath;
$postParam['page_url'] = $taegetPath . '/' . $fileName;
} else if (!empty($postParam['target_url']) && $postParam['target_url'] != $model['target_url'] && file_exists($model['page_url'])) {
// 没有修改文件,但是修改了目标url
$isR = is_readable($model['page_url']);
if (!$isR) {
$chmod = chmod_file($model['page_url'], '777');
if (!$chmod) return $this->renderError('更新目标URL 设置文件权限失败');
}
// 获取文件内容
try {
$fileContent = file_get_contents($model['page_url']);
} catch (\Exception $e) {
return $this->renderError('更新目标URL 读取文件失败' . $e->getMessage());
}
// 修改文件内容 替换全局a标签href的值
$newContent = preg_replace_callback(
'/<a\s[^>]*href="([^"]+)"[^>]*>(.*?)<\/a>/si',
function ($matches) use ($params) {
// 这里可以添加逻辑来处理 $matches[1](原始href值)
$newHref = $params['target_url'];
return "<a href=\"{$newHref}\">{$matches[2]}</a>";
},
$fileContent
);
// 写入内容到文件
$result = file_put_contents($model['page_url'], $newContent);
if (!$result) return $this->renderError('更新目标URL 写入文件失败');
}
// 更新记录
if ($model->edit($postParam)) {
return $this->renderSuccess('更新成功');
}
return $this->renderError($model->getError() ?: '更新失败');
}