FastDfS入門到精通


一,FastDFS簡介

  FastDFS是用c語言編寫的一款開源的分布式文件系統,它是由淘寶資深架構師余慶編寫並開源。FastDFS專為互聯網量身定制,充分考慮了冗余備份、負載均衡、線性擴容等機制,並注重高可用、高性能等指標,使用FastDFS很容易搭建一套高性能的文件服務器集群提供文件上傳、下載等服務。

優勢·:

  適合通用分部式,fastDFS非常適合存儲圖片等那些小文件,fastDFS不對文件進行分塊,所以它就沒有分塊合並的開銷,fastDFS網絡通信采用socket,通信速度很快。

二,服務器分為tracker和storage

三,上傳文件原理

storage將文件id返回客戶端

id中包含的信息

代碼實現:

1.工具類:

  1 import org.csource.common.NameValuePair;
  2 import org.csource.fastdfs.*;
  3 import org.slf4j.LoggerFactory;
  4 import org.springframework.core.io.ClassPathResource;
  5 
  6 import java.io.ByteArrayInputStream;
  7 import java.io.IOException;
  8 import java.io.InputStream;
  9 
 10 public class FastDFSClient {
 11     private static org.slf4j.Logger logger = LoggerFactory.getLogger(FastDFSClient.class);
 12 
 13     /***
 14      * 初始化加載FastDFS的TrackerServer配置
 15      */
 16     static {
 17         try {
 18             String filePath = new ClassPathResource("fdfs_client.conf").getFile().getAbsolutePath();;
 19             ClientGlobal.init(filePath);
 20         } catch (Exception e) {
 21             logger.error("FastDFS Client Init Fail!",e);
 22         }
 23     }
 24 
 25     /***
 26      * 文件上傳
 27      * @param file
 28      * @return
 29      */
 30     public static String[] upload(FastDFSFile file) {
 31         //獲取文件的作者
 32         NameValuePair[] meta_list = new NameValuePair[1];
 33         meta_list[0] = new NameValuePair("author", file.getAuthor());
 34 
 35         //接收返回數據
 36         String[] uploadResults = null;
 37         StorageClient storageClient=null;
 38         try {
 39             //創建StorageClient客戶端對象
 40             storageClient = getTrackerClient();
 41 
 42             /***
 43              * 文件上傳
 44              * 1)文件字節數組
 45              * 2)文件擴展名
 46              * 3)文件作者
 47              */
 48             uploadResults = storageClient.upload_file(file.getContent(), file.getExt(), meta_list);
 49         } catch (Exception e) {
 50             logger.error("Exception when uploadind the file:" + file.getName(), e);
 51         }
 52 
 53         if (uploadResults == null && storageClient!=null) {
 54             logger.error("upload file fail, error code:" + storageClient.getErrorCode());
 55         }
 56         //獲取組名
 57         String groupName = uploadResults[0];
 58         //獲取文件存儲路徑
 59         String remoteFileName = uploadResults[1];
 60         return uploadResults;
 61     }
 62 
 63     /***
 64      * 獲取文件信息
 65      * @param groupName:組名
 66      * @param remoteFileName:文件存儲完整名
 67      * @return
 68      */
 69     public static FileInfo getFile(String groupName, String remoteFileName) {
 70         try {
 71             StorageClient storageClient = getTrackerClient();
 72             return storageClient.get_file_info(groupName, remoteFileName);
 73         } catch (Exception e) {
 74             logger.error("Exception: Get File from Fast DFS failed", e);
 75         }
 76         return null;
 77     }
 78 
 79     /***
 80      * 文件下載
 81      * @param groupName
 82      * @param remoteFileName
 83      * @return
 84      */
 85     public static InputStream downFile(String groupName, String remoteFileName) {
 86         try {
 87             //創建StorageClient
 88             StorageClient storageClient = getTrackerClient();
 89 
 90             //下載文件
 91             byte[] fileByte = storageClient.download_file(groupName, remoteFileName);
 92             InputStream ins = new ByteArrayInputStream(fileByte);
 93             return ins;
 94         } catch (Exception e) {
 95             logger.error("Exception: Get File from Fast DFS failed", e);
 96         }
 97         return null;
 98     }
 99 
100 
101     /***
102      * 文件刪除
103      * @param groupName
104      * @param remoteFileName
105      * @throws Exception
106      */
107     public static void deleteFile(String groupName, String remoteFileName)
108             throws Exception {
109         //創建StorageClient
110         StorageClient storageClient = getTrackerClient();
111 
112         //刪除文件
113         int i = storageClient.delete_file(groupName, remoteFileName);
114     }
115 
116 
117     /***
118      * 獲取Storage組
119      * @param groupName
120      * @return
121      * @throws IOException
122      */
123     public static StorageServer[] getStoreStorages(String groupName)
124             throws IOException {
125         //創建TrackerClient
126         TrackerClient trackerClient = new TrackerClient();
127         //獲取TrackerServer
128         TrackerServer trackerServer = trackerClient.getConnection();
129         //獲取Storage組
130         return trackerClient.getStoreStorages(trackerServer, groupName);
131     }
132 
133     /***
134      * 獲取Storage信息,IP和端口
135      * @param groupName
136      * @param remoteFileName
137      * @return
138      * @throws IOException
139      */
140     public static ServerInfo[] getFetchStorages(String groupName,
141                                                 String remoteFileName) throws IOException {
142         TrackerClient trackerClient = new TrackerClient();
143         TrackerServer trackerServer = trackerClient.getConnection();
144         return trackerClient.getFetchStorages(trackerServer, groupName, remoteFileName);
145     }
146 
147     /***
148      * 獲取Tracker服務地址
149      * @return
150      * @throws IOException
151      */
152     public static String getTrackerUrl() throws IOException {
153         return "http://"+getTrackerServer().getInetSocketAddress().getHostString()+":"+ ClientGlobal.getG_tracker_http_port()+"/";
154     }
155 
156 
157     /***
158      * 獲取Storage客戶端
159      * @return
160      * @throws IOException
161      */
162     private static StorageClient getTrackerClient() throws IOException {
163         TrackerServer trackerServer = getTrackerServer();
164         StorageClient storageClient = new StorageClient(trackerServer, null);
165         return  storageClient;
166     }
167 
168 
169     /***
170      * 獲取Tracker
171      * @return
172      * @throws IOException
173      */
174     private static TrackerServer getTrackerServer() throws IOException {
175         TrackerClient trackerClient = new TrackerClient();
176         TrackerServer trackerServer = trackerClient.getConnection();
177         return  trackerServer;
178     }
179 }

 

2.啟動類

 1 import org.springframework.boot.SpringApplication;
 2 import org.springframework.boot.autoconfigure.SpringBootApplication;
 3 import org.springframework.cloud.netflix.eureka.EnableEurekaClient;
 4 
 5 @SpringBootApplication
 6 @EnableEurekaClient
 7 public class FileApplication {
 8     public static void main(String[] args) {
 9         SpringApplication.run( FileApplication.class );
10     }
11 }

 

3.FastDFSFile標准類

 1 public class FastDFSFile {
 2 
 3     //文件名字
 4     private String name;
 5     //文件內容
 6     private byte[] content;
 7     //文件擴展名
 8     private String ext;
 9     //文件MD5摘要值
10     private String md5;
11     //文件創建作者
12     private String author;
13 
14     public FastDFSFile(String name, byte[] content, String ext, String height,
15                        String width, String author) {
16         super();
17         this.name = name;
18         this.content = content;
19         this.ext = ext;
20         this.author = author;
21     }
22 
23     public FastDFSFile(String name, byte[] content, String ext) {
24         super();
25         this.name = name;
26         this.content = content;
27         this.ext = ext;
28     }
29 
30     public String getName() {
31         return name;
32     }
33 
34     public void setName(String name) {
35         this.name = name;
36     }
37 
38     public byte[] getContent() {
39         return content;
40     }
41 
42     public void setContent(byte[] content) {
43         this.content = content;
44     }
45 
46     public String getExt() {
47         return ext;
48     }
49 
50     public void setExt(String ext) {
51         this.ext = ext;
52     }
53 
54     public String getMd5() {
55         return md5;
56     }
57 
58     public void setMd5(String md5) {
59         this.md5 = md5;
60     }
61 
62     public String getAuthor() {
63         return author;
64     }
65 
66     public void setAuthor(String author) {
67         this.author = author;
68     }
69 }

 

 

4.上傳的類

 1 import org.springframework.web.bind.annotation.CrossOrigin;
 2 import org.springframework.web.bind.annotation.PostMapping;
 3 import org.springframework.web.bind.annotation.RequestParam;
 4 import org.springframework.web.bind.annotation.RestController;
 5 import org.springframework.web.multipart.MultipartFile;
 6 
 7 import java.io.IOException;
 8 
 9 @RestController
10 @CrossOrigin
11 public class FileController {
12 
13 
14     @PostMapping("/upload")
15     public String upload( @RequestParam("file") MultipartFile file){
16         try {
17             //1.獲取文件名
18             String fileName = file.getOriginalFilename();
19             //2.獲取文件內容
20             byte[] bytes = file.getBytes();
21             //3.獲取文件擴展名 .
22             String ext = fileName.substring( fileName.lastIndexOf( "." ) );
23             //4.封裝文件實體
24             FastDFSFile fastDFSFile=new FastDFSFile( fileName,bytes,ext );
25             //5.文件上傳
26             String[] result = FastDFSClient.upload( fastDFSFile );
27             //6.返回結果
28             String path = FastDFSClient.getTrackerUrl()+result[0]+"/"+result[1];
29             return path;
30 
31         } catch (IOException e) {
32             e.printStackTrace();
33             return "";
34         }
35     }
36 
37 }

yml文件

 1 server:
 2   port: 9008
 3 spring:
 4   application:
 5     name: file
 6   servlet:
 7     multipart:
 8       max-file-size: 10MB
 9       max-request-size: 10MB
10   main:
11     allow-bean-definition-overriding: true #當遇到同樣名字的時候,是否允許覆蓋注冊
12 eureka:
13   client:
14     service-url:
15       defaultZone: http://127.0.0.1:6868/eureka
16   instance:
17     prefer-ip-address: true

配置文件

connect_timeout = 60
network_timeout = 60
charset = UTF-8
http.tracker_http_port = 8080
tracker_server = 192.168.200.128:22122

 

四,文件下載

原理

有tracker根據id中的信息來決定從哪個storage中查詢

五,項目級別運用

(一)圖片文件上傳(對應1-5)

1.文件校驗(2)

//文件校驗
if (file == null){
ExceptionCast.cast(CommonCode.INVALIDATE_PARAMS);
}

2.上傳文件(3)

 1     
 2         //上傳文件
 3         String fileId = this.uploadFileToFastdfs(file);
 4         if (StringUtils.isEmpty(fileId)){
 5             ExceptionCast.cast(FileSystemCode.FS_UPLOADFILE_FILEISNULL);
 6         }
 7 
 8 private String uploadFileToFastdfs(MultipartFile file) {
 9 
10 
11         try {
12 
13             //初始化fastdfs
14             this.initFastdfs();
15 
16             //編寫上傳功能
17             TrackerClient trackerClient = new TrackerClient();
18             TrackerServer trackerServer = null;
19             trackerServer = trackerClient.getConnection();
20             StorageServer storageServer = trackerClient.getStoreStorage(trackerServer);
21             StorageClient1 storageClient1 = new StorageClient1(trackerServer,storageServer);
22 
23             String originalFilename = file.getOriginalFilename();
24             String extName = originalFilename.substring(originalFilename.lastIndexOf(".")+1);
25 
26             String fileId = storageClient1.upload_file1(file.getBytes(), extName, null);
27             return fileId;
28 
29         } catch (Exception e) {
30             e.printStackTrace();
31         }
32 
33         return null;
34 
35 
36     }
37 
38 
39     private void initFastdfs() {
40         try {
41             ClientGlobal.initByTrackers(tracker_servers);
42             ClientGlobal.setG_network_timeout(network_timeout_in_seconds);
43             ClientGlobal.setG_connect_timeout(connect_timeout_in_seconds);
44             ClientGlobal.setG_charset(charset);
45         } catch (Exception e) {
46             e.printStackTrace();
47         }
48     }

 

初始化fastDfs1

    private void initFastdfs() {
        try {
            ClientGlobal.initByTrackers(tracker_servers);
            ClientGlobal.setG_network_timeout(network_timeout_in_seconds);
            ClientGlobal.setG_connect_timeout(connect_timeout_in_seconds);
            ClientGlobal.setG_charset(charset);
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

 

,編寫上傳功能(4返回文件地址)

String fileId = storageClient1.upload_file1(file.getBytes(), extName, null);
      return fileId; 
 1     //編寫上傳功能
 2             TrackerClient trackerClient = new TrackerClient();
 3             TrackerServer trackerServer = null;
 4             trackerServer = trackerClient.getConnection();
 5             StorageServer storageServer = trackerClient.getStoreStorage(trackerServer);
 6             StorageClient1 storageClient1 = new StorageClient1(trackerServer,storageServer);
 7 
 8             String originalFilename = file.getOriginalFilename();
 9             String extName = originalFilename.substring(originalFilename.lastIndexOf(".")+1);
10 
11             String fileId = storageClient1.upload_file1(file.getBytes(), extName, null);
12             return fileId;
13 
14         } catch (Exception e) {
15             e.printStackTrace();
16         }
17 
18         return null;

 

3.存到mongodb(5,文件信息存到mongo庫)

 1  //將文件的id存入mongodb
 2         FileSystem fileSystem = new FileSystem();
 3 
 4         //設置值
 5         //文件id
 6         fileSystem.setFileId(fileId);
 7         //文件在文件系統中的路徑
 8         fileSystem.setFilePath(fileId);
 9         //業務標識
10         fileSystem.setBusinesskey(businesskey);
11         //標簽
12         fileSystem.setFiletag(filetag);
13         //元數據
14         if(StringUtils.isNotEmpty(metadata)){
15             try {
16                 Map map = JSON.parseObject(metadata, Map.class);
17                 fileSystem.setMetadata(map);
18             } catch (Exception e) {
19                 e.printStackTrace();
20             }
21         }
22         //名稱
23         fileSystem.setFileName(file.getOriginalFilename());
24         //大小
25         fileSystem.setFileSize(file.getSize());
26         //文件類型
27         fileSystem.setFileType(file.getContentType());
28 
29         fileSystemRepository.save(fileSystem);
30 
31         //返回結果
32         return new UploadFileResult(CommonCode.SUCCESS,fileSystem);
33     }

(二)圖片信息和課程信息綁定,並存到mysql(6-8)

課程管理服務負責將(一)中上傳的文件的圖片地址,與對應課程id進行綁定並保存在mysql數據庫,方便其他子系統使用。

添加方法

查詢方法

刪除方法

 1     @Override
 2     @PostMapping("/coursepic/add")
 3     public ResponseResult addCoursePic(String courseId, String pic) {
 4         return courseService.addCoursePic(courseId,pic);
 5     }
 6     
 7    
 8     @Override
 9     @PreAuthorize("hasAuthority('course_pic_list')")
10     @GetMapping("/coursepic/list/{courseId}")
11     public CoursePic findCoursePic(@PathVariable("courseId") String courseId) {
12         return courseService.findCoursePic(courseId);
13     }
14     @Override
15     @DeleteMapping("/coursepic/delete")
16     public ResponseResult delCoursePic(String courseId) {
17         return courseService.delCoursePic(courseId);
18     }

servcie

   /**
     * 保存課程圖片信息
     * @param courseId
     * @param pic
     * @return
     */
    public ResponseResult addCoursePic(String courseId, String pic) {

        Optional<CoursePic> coursePicOptional = coursePicRepository.findById(courseId);

        CoursePic coursePic = null;

        if (coursePicOptional.isPresent()){
            coursePic = coursePicOptional.get();
        }

        if (coursePic == null){
            coursePic = new CoursePic();
        }

        coursePic.setPic(pic);
        coursePic.setCourseid(courseId);
        coursePicRepository.save(coursePic);
        return new ResponseResult(CommonCode.SUCCESS);
    }

    /**
     * 查詢課程圖片
     * @param courseId
     * @return
     */
    public CoursePic findCoursePic(String courseId) {

        Optional<CoursePic> coursePicOptional = coursePicRepository.findById(courseId);
        if (coursePicOptional.isPresent()){
            return coursePicOptional.get();
        }

        return null;
    }

    /**
     * 刪除課程圖片
     * @param courseId 課程id
     * @return  ResponseResult(規范返回類型)
     */
    public ResponseResult delCoursePic(String courseId) {

        coursePicRepository.deleteById(courseId);
        return new ResponseResult(CommonCode.SUCCESS);
    }

dao

import com.xuecheng.filesystem.framework.domain.course.response.CoursePic;
import org.springframework.data.jpa.repository.JpaRepository;

public interface CoursePicRepository extends JpaRepository<CoursePic,String> {
}



免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM