参考博客http://blog.csdn.net/xyang81/article/details/52850667
tobato在今年9月份在官方Java客户端的基础上进行了大量重构,且提供了更多丰富的api,主要新增的特性如下:
1 对关键部分代码加入了单元测试,便于理解与服务端的接口交易,提高接口质量
2将以前对byte硬解析风格重构为使用 对象+注解 的形式,尽量增强了代码的可读性
3支持对服务端的连接池管理(commons-pool2)
4支持上传图片时候检查图片格式,并且自动生成缩略图
5和Springboot整合方便
源码下载地址:https://github.com/tobato/FastDFS_Client
整合到Springboot项目流程
1.先创建springboot工程
工程目录如下
添加springboot pom依赖
<parent> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-parent</artifactId> <version>1.4.2.RELEASE</version> </parent> <dependencies> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-thymeleaf</artifactId> </dependency> <!-- hot swapping, disable cache for template, enable live reload --> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-devtools</artifactId> <optional>true</optional> </dependency> <!-- Optional, for bootstrap --> <dependency> <groupId>org.webjars</groupId> <artifactId>bootstrap</artifactId> <version>3.3.7</version> </dependency> <dependency> <groupId>junit</groupId> <artifactId>junit</artifactId> <version>3.8.1</version> <scope>test</scope> </dependency> <dependency> <groupId>com.github.tobato</groupId> <artifactId>fastdfs-client</artifactId> <version>1.25.2-RELEASE</version> </dependency> <dependency> <groupId>org.apache.commons</groupId> <artifactId>commons-lang3</artifactId> <version>3.0</version> </dependency> </dependencies> <build> <finalName>fastdfsspringboot</finalName> <plugins> <plugin> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-maven-plugin</artifactId> </plugin> </plugins> </build>
将Fdfs配置引入项目
1 package com.cky.demo; 2 3 import com.github.tobato.fastdfs.FdfsClientConfig; 4 import org.springframework.boot.SpringApplication; 5 import org.springframework.boot.autoconfigure.SpringBootApplication; 6 import org.springframework.context.annotation.Import; 7 8 /** 9 * Created by chenkaiyang on 2017/11/30. 10 */ 11 @Import(FdfsClientConfig.class) 12 @SpringBootApplication 13 public class JingtongApplication { 14 public static void main(String[] args) { 15 SpringApplication.run(JingtongApplication.class, args); 16 } 17 }
application.properties
fdfs.soTimeout=1500
fdfs.connectTimeout=600
fdfs.thumbImage.width=150
fdfs.thumbImage.height=150
fdfs.trackerList[0]=192.168.0.204:22122
在项目中使用
客户端主要包括以下接口:
TrackerClient - TrackerServer接口
GenerateStorageClient - 一般文件存储接口 (StorageServer接口)
FastFileStorageClient - 为方便项目开发集成的简单接口(StorageServer接口)
AppendFileStorageClient - 支持文件续传操作的接口 (StorageServer接口)
基于FastFileStorageClient接口和springmvc提供的MultipartFile接口封装了一个简单的工具类,方便全局管理与调用。如下所示
1 package com.cky.demo.util; 2 3 import com.cky.demo.constant.AppConfig; 4 import com.cky.demo.constant.AppConstants; 5 import com.github.tobato.fastdfs.domain.StorePath; 6 import com.github.tobato.fastdfs.exception.FdfsUnsupportStorePathException; 7 import com.github.tobato.fastdfs.service.FastFileStorageClient; 8 import org.apache.commons.io.FilenameUtils; 9 import org.apache.commons.lang3.StringUtils; 10 import org.slf4j.Logger; 11 import org.slf4j.LoggerFactory; 12 import org.springframework.beans.factory.annotation.Autowired; 13 import org.springframework.stereotype.Component; 14 import org.springframework.web.multipart.MultipartFile; 15 16 import java.io.ByteArrayInputStream; 17 import java.io.IOException; 18 import java.nio.charset.Charset; 19 20 /** 21 * Created by chenkaiyang on 2017/11/30. 22 */ 23 @Component 24 public class FastDFSClientWrapper { 25 26 private final Logger logger = LoggerFactory.getLogger(FastDFSClientWrapper.class); 27 28 @Autowired 29 private FastFileStorageClient storageClient; 30 31 @Autowired 32 private AppConfig appConfig; // 项目参数配置 33 34 /** 35 * 上传文件 36 * @param file 文件对象 37 * @return 文件访问地址 38 * @throws IOException 39 */ 40 public String uploadFile(MultipartFile file) throws IOException { 41 StorePath storePath = storageClient.uploadFile(file.getInputStream(),file.getSize(), FilenameUtils.getExtension(file.getOriginalFilename()),null); 42 return getResAccessUrl(storePath); 43 } 44 45 /** 46 * 将一段字符串生成一个文件上传 47 * @param content 文件内容 48 * @param fileExtension 49 * @return 50 */ 51 public String uploadFile(String content, String fileExtension) { 52 byte[] buff = content.getBytes(Charset.forName("UTF-8")); 53 ByteArrayInputStream stream = new ByteArrayInputStream(buff); 54 StorePath storePath = storageClient.uploadFile(stream,buff.length, fileExtension,null); 55 return getResAccessUrl(storePath); 56 } 57 58 // 封装图片完整URL地址 59 private String getResAccessUrl(StorePath storePath) { 60 String fileUrl = AppConstants.HTTP_PRODOCOL + appConfig.getResHost() 61 + ":" + appConfig.getFdfsStoragePort() + "/" + storePath.getFullPath(); 62 return fileUrl; 63 } 64 65 /** 66 * 删除文件 67 * @param fileUrl 文件访问地址 68 * @return 69 */ 70 public void deleteFile(String fileUrl) { 71 if (StringUtils.isEmpty(fileUrl)) { 72 return; 73 } 74 try { 75 StorePath storePath = StorePath.praseFromUrl(fileUrl); 76 storageClient.deleteFile(storePath.getGroup(), storePath.getPath()); 77 } catch (FdfsUnsupportStorePathException e) { 78 logger.warn(e.getMessage()); 79 } 80 } 81 }
除了FastDFSClientWrapper类中用到的api,客户端提供的api还有很多,可根据自身的业务需求,将其它接口也添加到工具类中即可。如下所示:
1 // 上传文件,并添加文件元数据 2 StorePath uploadFile(InputStream inputStream, long fileSize, String fileExtName, Set<MateData> metaDataSet); 3 // 获取文件元数据 4 Set<MateData> getMetadata(String groupName, String path); 5 // 上传图片并同时生成一个缩略图 6 StorePath uploadImageAndCrtThumbImage(InputStream inputStream, long fileSize, String fileExtName, 7 Set<MateData> metaDataSet); 8 // 。。。
FastStorage ip和端口配置
1 package com.cky.demo.constant; 2 3 import org.springframework.beans.factory.annotation.Value; 4 import org.springframework.stereotype.Component; 5 6 /** 7 * Created by chenkaiyang on 2017/11/30. 8 */ 9 @Component 10 public class AppConfig { 11 12 @Value("${resHost}") 13 private String resHost; 14 @Value("${fdfsStoragePort}") 15 private String fdfsStoragePort; 16 17 public String getResHost() { 18 return resHost; 19 } 20 21 public void setResHost(String resHost) { 22 this.resHost = resHost; 23 } 24 25 public String getFdfsStoragePort() { 26 return fdfsStoragePort; 27 } 28 29 public void setFdfsStoragePort(String fdfsStoragePort) { 30 this.fdfsStoragePort = fdfsStoragePort; 31 } 32 }
返回图片的连接地址的协议
1 package com.cky.demo.constant; 2 3 /** 4 * Created by chenkaiyang on 2017/11/30. 5 */ 6 public class AppConstants { 7 8 public static final String HTTP_PRODOCOL = "http://"; 9 }
配置controller的页面跳转及上传接口
1 package com.cky.demo.controller; 2 3 import com.cky.demo.util.FastDFSClientWrapper; 4 import org.springframework.beans.factory.annotation.Autowired; 5 import org.springframework.stereotype.Controller; 6 import org.springframework.web.bind.annotation.RequestMapping; 7 import org.springframework.web.bind.annotation.RequestMethod; 8 import org.springframework.web.bind.annotation.RequestParam; 9 import org.springframework.web.bind.annotation.ResponseBody; 10 import org.springframework.web.multipart.MultipartFile; 11 12 import javax.servlet.http.HttpServletRequest; 13 import javax.servlet.http.HttpServletResponse; 14 import java.util.HashMap; 15 import java.util.Map; 16 17 /** 18 * Created by chenkaiyang on 2017/12/1. 19 */ 20 @Controller 21 public class MyController { 22 @Autowired 23 private FastDFSClientWrapper dfsClient; 24 25 @ResponseBody 26 @RequestMapping(value = "/upload", method = RequestMethod.POST) 27 public Map<String, String> upload(@RequestParam(value="file",required=false) MultipartFile file, HttpServletRequest request, HttpServletResponse response) throws Exception { 28 // 省略业务逻辑代码。。。 29 String imgUrl = dfsClient.uploadFile(file); 30 Map<String, String> map = new HashMap<>(); 31 map.put("url", imgUrl); 32 map.put("status", "success"); 33 // 。。。。 34 return map; 35 } 36 @RequestMapping(value = "/topage", method = RequestMethod.GET) 37 public String toIndex() { 38 return "01"; 39 } 40 }
到这里后端的代码就配置完成
下面开始配置前端代码
首先在rescources下面的static目录下的js目录下引入jquery-1.11.3min.js及ajaxfileupload.js
由于高版本的jquery里面会报找不到handleError
因此在ajaxfileupload.js里面开始加入下面的代码
handleError: function( s, xhr, status, e ) { // If a local callback was specified, fire it if ( s.error ) { s.error.call( s.context || s, xhr, status, e ); } // Fire the global callback if ( s.global ) { (s.context ? jQuery(s.context) : jQuery.event).trigger( "ajaxError", [xhr, s, e] ); } },
前端html代码
1 <!DOCTYPE html> 2 <html lang="en"> 3 <head> 4 <meta charset="UTF-8"/> 5 <title>Title</title> 6 <script src="js/jquery-1.11.3.min.js"></script> 7 <script src="js/ajaxfileupload.js"></script> 8 </head> 9 <body> 10 <p> 11 <label>ajax上传</label> 12 <input type="file" name="file" id="fileToUpload" class="inp_fileToUpload" multiple="multiple"/> 13 <img src="" width="400px" height="400px" class="img_upload" id="img" /> 14 </p> 15 <p> 16 <label>最新修改人员:</label> 17 <input readonly="readonly" type="text" size="30" /> 18 </p> 19 </body> 20 <script type="text/javascript"> 21 $(function() { 22 $(".inp_fileToUpload").on("change", function() {//现在这个已经适用于多个file表单。 23 ajaxFileUpload($(this).attr("id"), $(this).parent().children(".img_upload").attr("id")); 24 }) 25 }) 26 function ajaxFileUpload(file_id, img_id) { 27 jQuery.ajaxFileUpload({ 28 url : '/upload', //用于文件上传的服务器端请求地址 29 secureuri : false, //是否需要安全协议,一般设置为false 30 fileElementId : file_id, //文件上传域的ID 31 contentType:"application/json;charset=UTF-8", 32 success : function(data, status)//服务器成功响应处理函数 33 { 34 var str = $(data).find("body").text();//获取返回的字符串 35 var json = $.parseJSON(str);//把字符串转化为json对象 36 if(json.status){ 37 //alert("上传成功URL为" + json.url); 38 $("#"+img_id).attr("src", json.url) 39 } 40 else{ 41 alert("删除失败"); 42 } 43 }, 44 error : function(data, status, e)//服务器响应失败处理函数 45 { 46 alert(e); 47 } 48 }) 49 return false; 50 } 51 </script> 52 </html>
启动springboot
附送项目源码地址: