一、问题描述
某采购项目中,用户会在评标过程中主动上传一些与采购项目相关的视频,文件,图片类数据;据现场反应,用户浏览器页面下载视频,无法成功跳转,手动下载,文件名与系统页面显示文件名不一致,文件名显示为一串字符样式,对客户体验而言,类似乱码,体验较差。
项目所述介质存储在FDFS上。FastDFS是一个开源的轻量级的分布式文件系统,特别适合以中小文件(4KB < FileSize < 500MB)为载体的在线服务,如视频,音频,图片网站等等,是一个优良的大量数据存储和负载均衡问题的解决方案。
二、问题分析
1)上述问题中所述文件存在在平台环境FDFS 文件存储系统上,默认文件上传后,系统会以特定编码将文件名以一串字符来排序表示;
2)用浏览器下载时,点击下载会打开视频链接,但不会正确弹出下载窗口,视频课正常在线访问(在线播放),但下载时文件名显示如下类似:
原因: 当文件被上传到FastDFS后Storage服务端返回的文件索引(FID),其中文件名是根据FastDFS自定义规则重新生成的,而不是原始文件名,FastDFS不存储原始文件名,也没有提供恢复原始文件名的方法;用户通过浏览器下载时,使用http/https协议下载的url如不在web端进行处理,当用户点击下载,这时的url是用Nginx的域名+资源的FID+“attname=……”拼出的URL,浏览器读取该url时,资源文件名就会以FDFS“源名称”显示;针对以上问题,我们要做的就是如何将web服务(nginx)访问fdfs过程中,转化为attname而不是源文件名称;
三、问题处理
经咨询研发,某子项目出现过类似情况,通过修改nginx配置文件,配置以下参数,可将请求的文件名转化成attname的值:
}
location /group1/M00 {
alias /usr/local/fastdfs//file/data;
if ($arg_attname ~ "^(.+)") {
add_header Content-Type application/x-download;
add_header Content-Disposition "attachment;filename=$arg_attname";
}
通过以上配置,在Http响应头里面加上字段 Content-Disposition “attachment;filename=$arg_attname”,当用户的web请求到来时,Nginx就会截获url中的参数attname,从而显示“资源友好名称”。
四、验证
效果如下所示:
注: 另外,环境中的一些安防软件会限制web目录的访问权限,从而造成资源下载访问异常,如果遇到该问题,可参考检查排除。
五、附录:Fdfs文件上传下载流程
1)上传流程
其中文件名生成规则:
storage会为文件生成一个FileID,由storage server ip + 文件创建时间 + 文件大小 + 文件crc32 +随机数拼接。然后将这个二进制串进行base64编码,转换为可打印的字符串。storage会按文件fileid进行hash,路由到一个子目录,然后将文件以fileid为文件名存储到该子目录下,该文件生成一个文件名,文件名由group、存储目录、两级子目录、fileid、文件后缀名(由客户端指定,主要用于区分文件类型)拼接而成。
2)下载
下载时,跟上传类似,最终的资源请求还是由tracker来处理的,tracker可从文件名中解析出文件的group、大小、创建时间等信息,然后为该请求选择一个storage用来服务读取请求,最后将返回文件ID给客户端,访问到该文件的具体信息,根据定位到的文件,完成下载。
更多参看FastDFS 分布式文件存储。