图片服务器
1、存储空间可扩展。
2、提供一个统一的访问方式。
使用FastDFS,分布式文件系统。存储空间可以横向扩展,可以实现服务器的高可用。支持每个节点有备份机
FastDFS是一种轻量级的、常用的分布式文件系统,通常用作图片服务器。 可以解决图片存储空间扩容问题, 如果存储空间满了,可以加服务器,fastDFS会自动管理,如果服务器挂了,(备份机可以自动同步)另一台服务器可以继续提供服务(高可用)
分布式文件系统: 分布式环境, 可以把文件保存到多台服务器上
文件上传的流程
客户端上传文件后存储服务器将文件ID返回给客户端, 此文件ID用于以后访问该文件的索引信息. 文件索引信息包括: 组名, 虚拟磁盘路径, 数据两级目录, 文件名.
组名:文件上传后所在的storage组名称,在文件上传成功后有storage服务器返回,需要客户端自行保存。
虚拟磁盘路径:storage配置的虚拟路径,与磁盘选项store_path*对应。如果配置了store_path0则是M00,如果配置了store_path1则是M01,以此类推。
数据两级目录:storage服务器在每个虚拟磁盘路径下创建的两级目录,用于存储数据文件。
文件名:与文件上传时不同。是由存储服务器根据特定信息生成,文件名包含:源存储服务器IP地址、文件创建时间戳、文件大小、随机数和文件拓展名等信息。
文件下载的流程
图片服务器使用
图片服务器有一个java客户端, 想要使用需要把它加到工程中去
但是我们使用maven工程, 这个jar包在中央仓库中没有
就可以使用一个fastdfs_client的pom工程
fastdfs_client下载页面
把这个工程导入到
fastdfs_client的.pom文件里有这个jar包的坐标, 我们安装一下–Run As–>Maven install 本地仓库中就有这个jar包了, 需要使用的时候只需要把这个坐标加到依赖中就行了
上传图片测试
在表现层添加依赖
<dependency>
<groupId>fastdfs_client</groupId>
<artifactId>fastdfs_client</artifactId>
<version>1.25</version>
</dependency>
上传步骤
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、返回数组。包含组名和图片的路径
创建测试方法FastDfsTest
package cn.e3mall.fast;
import org.csource.fastdfs.ClientGlobal;
import org.csource.fastdfs.StorageClient;
import org.csource.fastdfs.StorageServer;
import org.csource.fastdfs.TrackerClient;
import org.csource.fastdfs.TrackerServer;
import org.junit.Test;
import cn.e3mall.common.util.FastDFSClient;
public class FastDfsTest {
@Test
public void testUpload() throws Exception{
//创建一个配置文件(client.conf),文件名任意,内容就是tracker服务器的地址(tracker_server=192.168.25.133:22122)
//使用全局对象加载配置文件
ClientGlobal.init("D:/Eclipse/Workspaces/e3-manager-web/src/main/resources/conf/client.conf");
//创建一个trackerClient对象
TrackerClient trackerClient = new TrackerClient();
//通过trackerClient获得一个TrackerServer对象
TrackerServer trackerServer = trackerClient.getConnection();
//创建一个StroageServer的引用,可以是null
StorageServer storageServer = null;
//创建一个StorageClient, 参数需要TrackerServer和StorageServer
StorageClient storageClient = new StorageClient(trackerServer, storageServer);
//使用StorageClient上传文件 三个参数 local_filename:本地文件的绝对路径 file_ext_name:扩展名 meta_list:源数据
String[] strings = storageClient.upload_file("C:/Users/11501/Pictures/Saved Pictures/a.jpg", "jpg", null);
for (String string : strings) {
System.out.println(string);
}
}
运行结果
通过返回的内容就可以访问图片了
能通过http方式访问到图片, 是因为安装了nginx.
nginx和fastDFS插件配合, 去访问的时候, 这个插件询问tracker到哪去下载图片, 实现下载流程, 访问到图片响应回来, 就可以通过http方式访问图片, fastDFS只是解决了图片保存问题, 通过HTTP方式访问必须安装nginx
使用工具类上传图片
FastDFSClient工具类下载页面
通过上面的测试方法, 会发现很麻烦, 这时候我们就需要使用工具类来完成流程了
把工具类上传至common
报错是因为没有依赖
在common里面加上依赖
<dependency>
<groupId>fastdfs_client</groupId>
<artifactId>fastdfs_client</artifactId>
<version>1.25</version>
</dependency>
FastDFSClient导入了, 这个工具类怎么用呢
还在刚刚的测试方法FastDfsTest 那再写一个测试方法
package cn.e3mall.fast;
import org.csource.fastdfs.ClientGlobal;
import org.csource.fastdfs.StorageClient;
import org.csource.fastdfs.StorageServer;
import org.csource.fastdfs.TrackerClient;
import org.csource.fastdfs.TrackerServer;
import org.junit.Test;
import cn.e3mall.common.util.FastDFSClient;
public class FastDfsTest {
@Test
//使用工具类的测试方法
public void testFastDfsClient() throws Exception{
FastDFSClient fastDFSClient = new FastDFSClient("D:/Eclipse/Workspaces/e3-manager-web/src/main/resources/conf/client.conf");
String string = fastDFSClient.uploadFile("C:/Users/11501/Pictures/Saved Pictures/b.jpg");
System.out.println(string);
}
}
运行结果
图片上传功能实现
有了工具类, 上传图片功能以及比较简单了, 接下来进行功能的实现
功能分析
使用的是KindEditor的多图片上传插件。
KindEditor 4.x 文档
http://kindeditor.net/doc.php
请求的url:/pic/upload
参数:MultiPartFile uploadFile
返回值:
图片上传
业务逻辑:
1、接收页面传递的图片信息uploadFile
2、把图片上传到图片服务器。使用封装的工具类实现。需要取文件的内容和扩展名。
3、图片服务器返回图片的url
4、将图片的url补充完整,返回一个完整的url。
5、把返回结果封装到一个Map对象中返回。
把文件上传组件的依赖添加到*-manager-web
<!-- 文件上传组件 -->
<dependency>
<groupId>commons-fileupload</groupId>
<artifactId>commons-fileupload</artifactId>
</dependency>
在springMVC.xml配置多媒体解析器
<!-- 配置多媒体解析器 -->
<!-- 定义文件上传解析器 -->
<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>
controller
import java.util.HashMap;
import java.util.Map;
import org.springframework.beans.factory.annotation.Value;
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 cn.e3mall.common.util.FastDFSClient;
import cn.e3mall.common.util.JsonUtils;
/**
* 图片上传的controller
* @author 11501
*/
@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();
//找到最后一个"." , +1不包含"."开始截取, 就能拿到扩展名了
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、拼接返回的url和ip地址,拼装成完整的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;
}
}
}
IMAGE_SERVER_URL内容
加载配置文件
解决浏览器兼容性的问题
KindEditor的图片上传插件,对浏览器兼容性不好
浏览器Content-Type是applocation/json
解决方法:
使用JsonUtils工具类实现java对象和jason之间的相互转换
JsonUtils工具类下载页面
把工具类导入到common中
使用@ResponseBody注解
不走逻辑视图, 直接响应浏览器, 相当于使用respond对象调用white方法, 往浏览器写入内容
如果返回值是对象, 会默认把对象变成json再进行响应
如果返回对象是字符串, 直接响应浏览器
上面我们手动转换成json字符串
返回值是字符串, 直接响应浏览器, 就不需要转换, content-type 就默认是 text/plan
KindEditor的多图片上传插件最后响应的Content-Type是text/plan格式的 json 字符串, 兼容性是最好的, 那么就解决了兼容性问题