FastDFS 图片服务器

本文介绍如何安装和配置FastDFS分布式文件系统,用于图片服务器的搭建。FastDFS支持文件存储空间的横向扩展,提供了高可用性和高性能的文件上传、下载服务。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

 

 

FastDFS

图片服务器

 

1. 图片服务器的安装

1、存储空间可扩展。

2、提供一个统一的访问方式。

 

使用FastDFS,分布式文件系统。存储空间可以横向扩展,可以实现服务器的高可用。支持每个节点有备份机。

 

1.1. 什么是FastDFS

FastDFS是用c语言编写的一款开源的分布式文件系统。FastDFS为互联网量身定制,充分考虑了冗余备份、负载均衡、线性扩容等机制,并注重高可用、高性能等指标,使用FastDFS很容易搭建一套高性能的文件服务器集群提供文件上传、下载等服务。

 

1.2. FastDFS架构

FastDFS架构包括 Tracker serverStorage server。客户端请求Tracker server进行文件上传、下载,通过Tracker server调度最终由Storage server完成文件上传和下载。

Tracker server作用是负载均衡和调度,通过Tracker server在文件上传时可以根据一些策略找到Storage server提供文件上传服务。可以将tracker称为追踪服务器或调度服务器。

Storage server作用是文件存储,客户端上传的文件最终存储在Storage服务器上,Storage server没有实现自己的文件系统而是利用操作系统 的文件系统来管理文件。可以将storage称为存储服务器。

 

 

服务端两个角色:

Tracker:管理集群,tracker也可以实现集群。每个tracker节点地位平等。

收集Storage集群的状态。

Storage:实际保存文件

Storage分为多个组,每个组之间保存的文件是不同的。每个组内部可以有多个成员,组成员内部保存的内容是一样的,组成员的地位是一致的,没有主从的概念。

 

1.3. 文件上传的流程

 

客户端上传文件后存储服务器文件ID返回给客户端,此文件ID用于以后访问该文件的索引信息。文件索引信息包括:组名,虚拟磁盘路径,数据两级目录,文件名。

 

 

组名:文件上传后所在的storage组名称,在文件上传成功后有storage服务器返回,需要客户端自行保存。

n 虚拟磁盘路径:storage配置的虚拟路径,与磁盘选项store_path*对应。如果配置了store_path0则是M00,如果配置了store_path1则是M01,以此类推。

n 数据两级目录:storage服务器在每个虚拟磁盘路径下创建的两级目录,用于存储数据文件。

文件名:与文件上传时不同。是由存储服务器根据特定信息生成,文件名包含:源存储服务器IP地址、文件创建时间戳、文件大小、随机数和文件拓展名等信息。

 

1.4. 文件下载

 

 

1.5. 最简单的FastDFS架构

 

 

2. 图片服务器安装方法

2.1. 安装步骤

第一步:把图片服务器解压缩。

第二步:把图片服务器添加到Vmware中。

第三步:Vmware的网络配置。

第四步:开机

3. 图片服务器使用

 

3.1. 上传图片

3.1.1. 上传步骤

1、加载配置文件,配置文件中的内容就是tracker服务的地址。

配置文件内容:tracker_server=192.168.25.133:22122

2、创建一个TrackerClient对象。直接new一个。

3、使用TrackerClient对象创建连接,获得一个TrackerServer对象。

4、创建一个StorageServer的引用,值为null

5、创建一个StorageClient对象,需要两个参数TrackerServer对象、StorageServer的引用

6、使用StorageClient对象上传图片。

7、返回数组。包含组名和图片的路径。

 

3.1.2. 代码

public class FastDFSTest {

 

@Test

public void testFileUpload() throws Exception {

// 1、加载配置文件,配置文件中的内容就是tracker服务的地址。

ClientGlobal.init("D:/manager-web/src/main/resources/resource/client.conf");

// 2、创建一个TrackerClient对象。直接new一个。

TrackerClient trackerClient = new TrackerClient();

// 3、使用TrackerClient对象创建连接,获得一个TrackerServer对象。

TrackerServer trackerServer = trackerClient.getConnection();

// 4、创建一个StorageServer的引用,值为null

StorageServer storageServer = null;

// 5、创建一个StorageClient对象,需要两个参数TrackerServer对象、StorageServer的引用

StorageClient storageClient = new StorageClient(trackerServer, storageServer);

// 6、使用StorageClient对象上传图片。

//扩展名不带“.”

String[] strings = storageClient.upload_file("D:/Documents/Pictures/images/

55127886.jpg", "jpg", null);

// 7、返回数组。包含组名和图片的路径。

for (String string : strings) {

System.out.println(string);

}

}

}

 

3.2. 使用工具类上传

 

 

@Test

public void testFastDfsClient() throws Exception {

FastDFSClient fastDFSClient = new FastDFSClient("D://src/main/resources/resource/client.conf");

String file = fastDFSClient.uploadFile("D:/Documents/Pictures/images/2f2eb938943d.jpg");

System.out.println(file);

}

 

业务逻辑:

1、接收页面传递的图片信息uploadFile

2、把图片上传到图片服务器。使用封装的工具类实现。需要取文件的内容和扩展名。

3、图片服务器返回图片的url

4、将图片的url补充完整,返回一个完整的url

5、把返回结果封装到一个Map对象中返回。

 

 

1、需要把commons-iofileupload jar包添加到工程中。

2、配置多媒体解析器。

<!-- 定义文件上传解析器 -->

<bean id="multipartResolver"

class="org.springframework.web.multipart.commons.CommonsMultipartResolver">

<!-- 设定默认编码 -->

<property name="defaultEncoding" value="UTF-8"></property>

<!-- 设定文件上传的最大值5MB,5*1024*1024 -->

<property name="maxUploadSize" value="5242880"></property>

</bean>

 

3.3. Controller

@Controller

public class PictureController {

@Value("${IMAGE_SERVER_URL}")

private String IMAGE_SERVER_URL;

 

@RequestMapping("/pic/upload")

@ResponseBody

public Map fileUpload(MultipartFile uploadFile) {

try {

//1、取文件的扩展名

String originalFilename = uploadFile.getOriginalFilename();

String extName = originalFilename.substring(originalFilename.lastIndexOf(".") + 1);

//2、创建一个FastDFS的客户端

FastDFSClient fastDFSClient = new FastDFSClient("classpath:resource/client.conf");

//3、执行上传处理

String path = fastDFSClient.uploadFile(uploadFile.getBytes(), extName);

//4、拼接返回的urlip地址,拼装成完整的url

String url = IMAGE_SERVER_URL + path;

//5、返回map

Map result = new HashMap<>();

result.put("error", 0);

result.put("url", url);

return result;

} catch (Exception e) {

e.printStackTrace();

//5、返回map

Map result = new HashMap<>();

result.put("error", 1);

result.put("message", "图片上传失败");

return result;

}

}

}

 

3.4. 解决浏览器兼容性的问题

KindEditor的图片上传插件,对浏览器兼容性不好。

使用@ResponseBody注解返回java对象,

Content-Type:application/json;charset=UTF-8

 

返回字符串时:

Content-Type:text/plan;charset=UTF-8

 

 

指定响应结果的content-type

 

KindEditor的多图片上传插件最后响应的content-typetext/plan格式的json字符串。兼容性是最好的。

=========================================================================

springmvc里配置  /文件上传 /
springmvc扫描配置文件client.conf  里面存放着tracker IP和端口号

FastDFSClient 工具类 

springmvc.xml

<?xml version="1.0" encoding="UTF-8"?>
<beans xmlns="http://www.springframework.org/schema/beans"
xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xmlns:p="http://www.springframework.org/schema/p"
xmlns:context="http://www.springframework.org/schema/context"
xmlns:dubbo="http://code.alibabatech.com/schema/dubbo" xmlns:mvc="http://www.springframework.org/schema/mvc"
xsi:schemaLocation="
http://www.springframework.org/schema/beans 
http://www.springframework.org/schema/beans/spring-beans-4.2.xsd
http://code.alibabatech.com/schema/dubbo 
http://code.alibabatech.com/schema/dubbo/dubbo.xsd
        http://www.springframework.org/schema/mvc 
        http://www.springframework.org/schema/mvc/spring-mvc-4.2.xsd
        http://www.springframework.org/schema/context 
        http://www.springframework.org/schema/context/spring-context-4.2.xsd">
<!-- 加载配置文件 -->
<context:property-placeholder location="classpath:conf/*.properties" />
<context:component-scan base-package="com.lingwo.controller" />
<!-- 装换器 -->
<mvc:annotation-driven/>




<!-- 文件上传 -->
<bean id="multipartResolver"
class="org.springframework.web.multipart.commons.CommonsMultipartResolver">
<!-- 设定默认编码 -->
<property name="defaultEncoding" value="UTF-8"></property>
<!-- 设定文件上传的最大值5MB,5*1024*1024 -->
<property name="maxUploadSize" value="5242880"></property>
</bean>







<!-- 视图解析器 -->
<bean
class="org.springframework.web.servlet.view.InternalResourceViewResolver">
<property name="prefix" value="/sys/" />
<property name="suffix" value=".jsp" />
</bean>
<!-- 配置资源映射 -->
<mvc:resources location="/css/" mapping="/css/**" />
<mvc:resources location="/js/" mapping="/js/**" />








</beans>

client.conf

tracker_server=192.168.25.133:22122

FastDFSClient.java

package com.lingwo.common.utils;


import org.csource.common.NameValuePair;
import org.csource.fastdfs.ClientGlobal;
import org.csource.fastdfs.StorageClient1;
import org.csource.fastdfs.StorageServer;
import org.csource.fastdfs.TrackerClient;
import org.csource.fastdfs.TrackerServer;


public class FastDFSClient {


private TrackerClient trackerClient = null;
private TrackerServer trackerServer = null;
private StorageServer storageServer = null;
private StorageClient1 storageClient = null;

public FastDFSClient(String conf) throws Exception {
if (conf.contains("classpath:")) {
conf = conf.replace("classpath:", this.getClass().getResource("/").getPath());
}
ClientGlobal.init(conf);
trackerClient = new TrackerClient();
trackerServer = trackerClient.getConnection();
storageServer = null;
storageClient = new StorageClient1(trackerServer, storageServer);
}

/**
* 上传文件方法
* <p>Title: uploadFile</p>
* <p>Description: </p>
* @param fileName 文件全路径
* @param extName 文件扩展名,不包含(.)
* @param metas 文件扩展信息
* @return
* @throws Exception
*/
public String uploadFile(String fileName, String extName, NameValuePair[] metas) throws Exception {
String result = storageClient.upload_file1(fileName, extName, metas);
return result;
}

public String uploadFile(String fileName) throws Exception {
return uploadFile(fileName, null, null);
}

public String uploadFile(String fileName, String extName) throws Exception {
return uploadFile(fileName, extName, null);
}

/**
* 上传文件方法
* <p>Title: uploadFile</p>
* <p>Description: </p>
* @param fileContent 文件的内容,字节数组
* @param extName 文件扩展名
* @param metas 文件扩展信息
* @return
* @throws Exception
*/
public String uploadFile(byte[] fileContent, String extName, NameValuePair[] metas) throws Exception {

String result = storageClient.upload_file1(fileContent, extName, metas);
return result;
}

public String uploadFile(byte[] fileContent) throws Exception {
return uploadFile(fileContent, null, null);
}

public String uploadFile(byte[] fileContent, String extName) throws Exception {
return uploadFile(fileContent, extName, null);
}
}

PictureController.java

package com.lingwo.controller;


import java.util.HashMap;
import java.util.Map;


import org.springframework.beans.factory.annotation.Value;
import org.springframework.http.MediaType;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.ResponseBody;
import org.springframework.web.multipart.MultipartFile;


import com.lingwo.common.utils.FastDFSClient;
import com.lingwo.common.utils.JsonUtils;


/**
 * 图片上传
 * <p>Title: PictureController</p>
 * <p>Description: </p>
 * <p>Company: www.itcast.cn</p> 
 * @version 1.0
 */
@Controller
public class PictureController {

@Value("${IMAGE_SERVER_URL}")
private String IMAGE_SERVER_URL;


//produces解决浏览器兼容问题

@RequestMapping(value="/pic/upload",produces=MediaType.TEXT_PLAIN_VALUE+";charset=utf-8")
@ResponseBody
public String uploadFile(MultipartFile uploadFile){
try {
//把图片上传到服务器
FastDFSClient fastDFSClient = new FastDFSClient("classpath:conf/client.conf");
String originalFilename = uploadFile.getOriginalFilename();
String extName = originalFilename.substring(originalFilename.lastIndexOf(".")+1);
//得到图片地址和文件名
String url = fastDFSClient.uploadFile(uploadFile.getBytes(),extName);
url = IMAGE_SERVER_URL+url;
Map result = new HashMap<>();
result.put("error", 0);
result.put("url", url);
return JsonUtils.objectToJson(result);
} catch (Exception e) {
// TODO: handle exception
Map result = new HashMap<>();
result.put("error", 1);
result.put("message", "图片上传失败");
return JsonUtils.objectToJson(result);
}

}
}
fastdfs文件下载

/**
* 文件下载
* @param file_id  group1/M00/00/00/wKgZhVrSDpqAQhTQAACwRZXTwcU030.jpg
* @return byte[]
* @throws Exception
*/
public byte[] downloadFile(String file_id) throws Exception {
byte[] result = storageClient1.download_file1(file_id);
return result;
}

fileController.java

package com.lingwo.controller;


import javax.servlet.ServletOutputStream;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;


import org.apache.commons.io.IOUtils;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;


import com.lingwo.common.utils.FastDFSClient;
import com.lingwo.common.utils.FileUtils;


@Controller
public class FileController {
/**
* 文件下载
* @param request
* @param response
*/
@RequestMapping(value="/download")
public void down(HttpServletRequest request,HttpServletResponse response){
try {
//创建连接对象
FastDFSClient fastDFSClient = new FastDFSClient("classpath:conf/client.conf");
//文件名,可以从数据库查,同时文件路径也可以从数据库查(文件路径file_id)
String filename = "图片1.jpg";
String contentType = request.getSession().getServletContext().getMimeType(filename);
response.setContentType(contentType);
String agent = request.getHeader("User-Agent");
//有返回值的,不接收就白搭了
filename = FileUtils.encodeDownloadFilename(filename, agent);
response.setHeader("content-disposition", "attachment;filename="+filename);
String file_id = "group1/M00/00/00/wKgZhVrSDpqAQhTQAACwRZXTwcU030.jpg";
byte[] downloadFile = fastDFSClient.downloadFile(file_id);
ServletOutputStream outputStream = response.getOutputStream();
IOUtils.write(downloadFile, outputStream);
} catch (Exception e) {

e.printStackTrace();
}


}
}



 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值