Vue-Element-Admin拦截器和Hyperf后端中间件修改,使用Header头内容作为下载的文件名踩坑记录
2023-12-02 00:02:04
好的,请看由AI螺旋创作器创作的文章:
正文
前言&回顾
最近在使用vue-element-admin开发后台,可以看看之前的文章心路历程:
正文开始
最近在项目中遇到一个需求,需要将服务器端导出的文件重命名,并使用文件名中的信息作为文件名。
经过一番调研,我发现可以通过修改vue-element-admin拦截器和Hyperf后端中间件来实现这一需求。
修改vue-element-admin拦截器
首先,我们需要修改vue-element-admin的拦截器。
在项目中,我们可以找到一个名为src/plugins/axios.js
的文件,这个文件是用来配置axios的。
// Axios plugin setup
const axios = axiosCreate(process.env.VUE_APP_API_BASE_URL)
axios.interceptors.request.use(
config => {
config.headers['Content-Type'] = 'application/json'
// Do something before request is sent
return config
},
error => {
// Do something with request error
return Promise.reject(error)
}
)
axios.interceptors.response.use(
response => {
// Do something before response is sent
return response
},
error => {
// Do something with response error
return Promise.reject(error)
}
)
export default function (app) {
app.config.globalProperties.$axios = axios
}
在这个文件中,我们可以看到有一个名为interceptors.response.use
的拦截器。
我们可以通过这个拦截器来修改服务器端返回的响应数据。
在interceptors.response.use
拦截器中,我们可以添加如下代码:
// 如果是下载文件,则重命名文件名
if (response.headers['content-type'].indexOf('application/octet-stream') !== -1) {
const filename = response.headers['content-disposition'].split('filename=')[1]
response.data = {
name: decodeURIComponent(filename),
data: response.data
}
}
// 返回修改后的响应数据
return response
这段代码的作用是,如果服务器端返回的是一个文件,则将文件重命名为content-disposition
头中的文件名。
修改Hyperf后端中间件
修改完vue-element-admin的拦截器后,我们还需要修改Hyperf后端中间件。
在项目中,我们可以找到一个名为config/middleware.php
的文件,这个文件是用来配置Hyperf中间件的。
<?php
return [
// 中间件列表,放在最前面的中间件优先执行
'http' => [
// 允许跨域请求的中间件
Hyperf\HttpServer\Middleware\CorsMiddleware::class,
// PSR-15 标准响应式中间件,会调用响应对象的 send 方法
Hyperf\HttpServer\Middleware\PsrResponseMiddleware::class,
// 记录请求和响应日志
Hyperf\HttpServer\Middleware\RequestLoggerMiddleware::class,
],
// WebSocket 监听
'ws' => [
// 默认中间件,记录 WebSocket 的请求和响应
Hyperf\WebSocketServer\Middleware\WebSocketMiddleware::class,
],
];
在这个文件中,我们可以看到有一个名为http
的中间件组。
我们可以通过这个中间件组来修改服务器端发送的响应头。
在http
中间件组中,我们可以添加如下代码:
'Hyperf\HttpServer\Middleware\ResponseMiddleware::class',
这段代码的作用是,将Hyperf\HttpServer\Middleware\ResponseMiddleware
中间件添加到中间件组中。
这个中间件可以用来修改服务器端发送的响应头。
在Hyperf\HttpServer\Middleware\ResponseMiddleware
中间件中,我们可以添加如下代码:
// 设置下载文件的文件名
if ($response instanceof \Hyperf\HttpMessage\Stream\Response) {
$filename = $request->header('filename', $response->filename());
$response = $response->withHeader('Content-Disposition', 'attachment; filename="' . rawurlencode($filename) . '"');
}
// 返回修改后的响应对象
return $response;
这段代码的作用是,如果服务器端返回的是一个文件,则将文件的名称设置为filename
头中的值。
踩坑记录
在实现这个需求的过程中,我遇到了以下几个坑:
- 坑1:
content-disposition
头中的文件名乱码
在修改vue-element-admin的拦截器时,我发现content-disposition
头中的文件名是乱码的。
经过一番调试,我发现这是因为服务器端发送的文件名是经过编码的。
为了解决这个问题,我需要在服务器端对文件名进行解码。
- 坑2:
filename
头不起作用
在修改Hyperf后端中间件时,我发现filename
头不起作用。
经过一番调试,我发现这是因为服务器端没有设置filename
头。
为了解决这个问题,我需要在服务器端设置filename
头。
总结
通过修改vue-element-admin拦截器和Hyperf后端中间件,我们可以实现使用Header头内容作为下载的文件名。
希望这篇文章对有需要的读者有所帮助。