FastDFS 使用经验分享

经验一:FastDFS文件下载恢复原始文件名

应用背景

文件被上传到FastDFS后Storage服务端将返回的文件索引(FID),其中文件名是根据FastDFS自定义规则重新生成的,而不是原始文件名,例如: group2/M00/00/89/eQ6h3FKJf_PRl8p4AUz4wO8tqaA688.apk

使用http下载时如不加处理,显示给用户的文件名会是这样的eQ6h3FKJf_PRl8p4AUz4wO8tqaA688.apk,这样的用户体验很不好。由于FastDFS不会存储原始文件名,也没有提供恢复原始文件名的方法,所以需要应用系统自己想办法恢复原始文件名。

解决方法

通过在项目中多次尝试,找到一种较简单的实现方法,实现过程如下:

一. 应用系统在上传文件到FastDFS成功时将原始文件名“文件索引(FID)”保存下来(例如:保存到数据库)。

二. 用户点击下载的时用Nginx的域名FID拼出url,然后在url后面增加一个参数,指定原始文件名。例如:http://121.14.161.48:9030/group2/M00/00/89/eQ6h3FKJf_PRl8p4AUz4wO8tqaA688.apk?attname=filename.apk

三. 在Nginx上进行如下配置,这样Nginx就会截获url中的参数attname,在Http响应头里面加上字段 Content-Disposition “attachment;filename=$arg_attname”。

location /group2/M00 {
root /data/store/data;
if ($arg_attname ~ "^(.*).apk") {
    add_header Content-Disposition "attachment;filename=$arg_attname";
}
ngx_fastdfs_module;
}

四,浏览器发现响应头里面有Content-Disposition “attachment;filename=$arg_attname”时,就会把文件名显示成filename指定的名称。

完整的请求和响应消息如下:

请求包:

Request URL:http://121.14.161.48:9030/group2/M00/00/89/eQ6h3FKJf_PRl8p4AUz4wO8tqaA688.apk?attname=filename.apk
Request Method:GET
Status Code:200 OK
Request Headersview source
Accept:text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Accept-Encoding:gzip,deflate,sdch
Accept-Language:zh-CN,zh;q=0.8,en;q=0.6
Connection:keep-alive
Host:121.14.161.48:9030
Referer:http://appandroidpcfront.test.uae.uc.cn/apps
User-Agent:Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/31.0.1650.57 Safari/537.36
Query String Parametersview sourceview URL encoded
attname:filename.apk

返回包:

Response Headersview source
Accept-Ranges:bytes
Connection:keep-alive
Content-Disposition:attachment;filename=filename.apk
Content-Length:21821632
Date:Thu, 28 Nov 2013 11:40:46 GMT
Last-Modified:Mon, 18 Nov 2013 02:48:19 GMT
Server:nginx/1.4.3

经验二:从文件的使用技巧

应用背景

使用FastDFS存储一个图片的多个分辨率的备份时,希望只记录源图的FID,并能将其它分辨率的图片与源图关联。可以使用从文件方法。

解决方法

名词注解:主从文件是指文件ID有关联的文件,一个主文件可以对应多个从文件。

  • 主文件ID = 主文件名 + 主文件扩展名
  • 从文件ID = 主文件名 + 从文件后缀名 + 从文件扩展名

以本场景为例:主文件为原始图片,从文件为该图片的一张或多张缩略图。

流程说明:

  1. 先上传主文件(即:原文件),得到主文件FID
  2. 然后上传从文件(即:缩略图,自己压缩,fastdfs不管),指定主文件FID和从文件后缀名,上传后得到从文件FID。

java伪代码,如下:

public class FastDFSUtils {    
private static Logger logger = Logger.getLogger(FastDFSUtils.class);
static{
    try {
        ClientGlobal.init("D:/WorkSpace/app-filesystem/conf/fdfs_client.conf");
    } catch (Exception e) {
        throw new RuntimeException(e);
    }
}

public static String uploadFile(String filePath) throws Exception{        
    String fileId = ""; 
    String fileExtName = ""; 
    if (filePath.contains(".")) { 
        fileExtName = filePath.substring(filePath.lastIndexOf(".") + 1); 
    } else { 
        logger.warn("Fail to upload file, because the format of filename is illegal."); 
        return fileId; 
    } 

    //建立连接 
    /*.......*/

    //上传文件 
    try { 
        fileId = client.upload_file1(filePath, fileExtName, null); 
    } catch (Exception e) { 
        logger.warn("Upload file \"" + filePath + "\"fails"); 
    }finally{
        trackerServer.close();
    }        
    return fileId; 
}

public static String uploadSlaveFile(String masterFileId, String prefixName, String slaveFilePath) throws Exception{
    String slaveFileId = ""; 
    String slaveFileExtName = ""; 
    if (slaveFilePath.contains(".")) { 
        slaveFileExtName = slaveFilePath.substring(slaveFilePath.lastIndexOf(".") + 1); 
    } else { 
        logger.warn("Fail to upload file, because the format of filename is illegal."); 
        return slaveFileId; 
    } 

    //建立连接 
    /*.......*/

    //上传文件 
    try { 
        slaveFileId = client.upload_file1(masterFileId, prefixName, slaveFilePath, slaveFileExtName, null); 
    } catch (Exception e) { 
        logger.warn("Upload file \"" + slaveFilePath + "\"fails"); 
    }finally{
        trackerServer.close();
    }

    return slaveFileId;
}

public static int download(String fileId, String localFile) throws Exception{   
    int result = 0;
    //建立连接 
    TrackerClient tracker = new TrackerClient();
    TrackerServer trackerServer = tracker.getConnection();
    StorageServer storageServer = null;
    StorageClient1 client = new StorageClient1(trackerServer, storageServer); 

    //上传文件 
    try { 
        result = client.download_file1(fileId, localFile); 
    } catch (Exception e) { 
        logger.warn("Download file \"" + localFile + "\"fails"); 
    }finally{
        trackerServer.close();
    }

    return result;
}

public static void main(String[] args) {
    try {
            String masterFileId = uploadFile("D:/Tmp/apk/t01134ede0e696735e7.png");
            System.out.println(masterFileId);
            download(masterFileId, "D:/Tmp/apk/master.png");

            String slaveFileId = uploadSlaveFile(masterFileId, "_120x120", "D:/Tmp/apk/PC.png");
            System.out.println(slaveFileId);

            download(slaveFileId, "D:/Tmp/apk/slave.png");
        } catch (Exception e) {
            logger.error("upload file to FastDFS failed.", e);
        }
    }
}

上面代码运行后打印的文件Id为:

  • 主文件:group1/M00/00/00/wKhbylJx1zkIAAAAAAApPcQL87AAAAAAQCmDxUAAClV522.png
  • 从文件:group1/M00/00/00/wKhbylJx1zkIAAAAAAApPcQL87AAAAAAQCmDxUAAClV522_120x120.png

注意:

FastDFS中的主从文件只是在文件ID上有联系。FastDFS server端没有记录主从文件对应关系,因此删除主文件,FastDFS不会自动删除从文件。删除主文件后,从文件的级联删除,需要由应用端来实现。

时间: 2024-11-03 15:38:45

FastDFS 使用经验分享的相关文章

虚拟化技术的实际使用经验分享

根据美国<CIO>杂志对于虚拟化技术(Virtualization)的第一手调查,你可能已实际使用过虚拟化技术,而且也满意目前为止它所带来的投资回报率.但是这个今日最热门的IT技术,却也引起棘手的技术与政治挑战,令你头痛不已. 最大的挑战――首先,算出在不降低“应用程序服务等级(Application Service Levels)”的情况下,你能借助使用更多的虚拟机器(Virtual Machine,VM)而省掉的实际物理服务器数量.其次,集结各个IT部门的专家,一起规划并管理虚拟化环境.I

jqGrid使用经验分享(一)——jqGrid简单使用、json格式和jsonReader介绍

广大的读者朋友们大家好,很高兴又可以在博客中和大家分享我的开发经验了. 此次,我准备向大家介绍一个非常好用的jQuery表格插件——jqGrid. 如果您在实际项目中遇到web端表格展示功能的需求,又不知道到底该使用那种技术实现时,jqGrid绝对是您的不二之选. 如果您已经决定使用jqGrid技术完成项目中表格展示功能,又苦于没有详细的使用说明迟迟不能实际开发时,本系列博客绝对是您的不二之选. 本篇博客将为大家介绍一下内容: jqGrid简单使用: jqGrid常用选项具体含义简介: jqGr

酷划锁屏手机赚钱APP的使用经验分享

酷划的奖励机制: 解锁手机2分-4分:下载安装推荐手机软件获得0.1元奖励,每天解锁屏幕.下载软件获取收益,还可以进行各种抽奖活动 酷划属于解锁赚钱软件,玩法简单,每次开启手机,看到界面的数字,勇敢划过去你就获得收益了.不用存款,每日收益远超余额宝.注册时填写我的邀请码:889182554 奖励5元.支持充话费.Q币.支付宝提现,购买商城实物.看我半个月的收益,到现在用酷划有段时间了,赚的钱还差点就能买了一部小米Note,太高兴了.下载通道→http://www.coohua.cn/ 酷划还有一

dubbo学习过程、使用经验分享及实现原理简单介绍

一.前言 部门去年年中开始各种改造,第一步是模块服务化,这边初选dubbo试用在一些非重要模块上,慢慢引入到一些稍微重要的功能上,半年时间,学习过程及线上使用遇到的些问题在此总结下. 整理这篇文章差不多花了两天半时间,请尊重劳动成果,如转载请注明出处http://blog.csdn.net/hzzhoushaoyu/article/details/43273099 二.什么是dubbo Dubbo是阿里巴巴提供的开源的SOA服务化治理的技术框架,据说只是剖出来的一部分开源的,但一些基本的需求已经

下一代java开发工具IDEA,使用经验分享

快捷键(90%常用键): 查阅源码常用: Ctrl+N 查询类 Ctrl+D/X 行复制行删除 Ctrl+Q 简短的方法说明 Ctrl+Alt+点击,方法实现 Ctrl+/ 修改keyMap,completcode.补全代码 Ctrl+ Alt +方向左键 ,返回上一个光标处 Ctrl + Alt + L         格式化代码 Ctrl + Alt + O         优化import Ctrl + shift + "+/-"  折叠代码 Shift+F6    更改变量名

【dubbo基础】dubbo学习过程、使用经验分享及实现原理简单介绍

一.前言 部门去年年中开始各种改造,第一步是模块服务化,这边初选dubbo试用在一些非重要模块上,慢慢引入到一些稍微重要的功能上,半年时间,学习过程及线上使用遇到的些问题在此总结下. 整理这篇文章差不多花了两天半时间,请尊重劳动成果,如转载请注明出处http://blog.csdn.NET/hzzhoushaoyu/article/details/43273099 二.什么是dubbo Dubbo是阿里巴巴提供的开源的SOA服务化治理的技术框架,据说只是剖出来的一部分开源的,但一些基本的需求已经

MongoDB Replica Set使用经验分享

MongoDB Replica Set是MongoDB官方推荐的主从复制和高可用方案,用于替代原有的Master-Slave主从复制方案.Replicat Set具有自动切换功能,当Primary挂掉之后,可以自动由Replica Set中的某一个Secondary来切换到Primary,以实现高可用的目的,不像MySQL那样需要使用第三方软件. 目前很多游戏公司都开始使用MongoDB作为数据库,我们公司线上使用的版本是2.4.6. 一  MongoDB Replica Set的原理 复制主要

JUnit测试框架的使用经验分享

1.学习Junit框架的使用可通过以下两个示例进行学习.A.Junit使用方法示例11)把Junit引入当前项目库中新建一个 Java 工程—coolJUnit,打开项目coolJUnit 的属性页 -> 选择“Java Build Path”子选项 -> 点选“Add Library…”按钮 -> 在弹出的“Add Library”对话框中选择 JUnit,并在下一页中选择版本 Junit 4 后点击“Finish”按钮.这样便把 JUnit 引入到当前项目库中了.2)新建单元测试代码

easyui datagrid可编辑表格使用经验分享

文章目录 1相关接口方法 2列属性formatter 3编辑器类型 3.1基于my97的编辑器 3.2简单的密码编辑器 3.3动态增加/删除编辑器 4字段的级联操作 4.1combobox的级联操作 4.2文本类型编辑器的级联 4.3编辑字段对非编辑字段的依赖 5数据提交与恢复 5.1利用loading提高用户体验 5.2结束编辑后获取原始数据 6常见问题集锦 6.1表头和数据表格错位 7效果演示 对于Easyui的可编辑表格,个人也是较为陌生的,尽管在操作方式上可能比使用表单修改的方式便捷,但