天天看點

docker安裝fastDFS檔案存儲,并與springMVC內建

因為項目需要搭建檔案伺服器,研究後,最後選型FastDFS分布式檔案存儲系統。

由于docker鏡像安裝的友善化,是以決定采用docker安裝。

拉取鏡像

docker pull morunchang/fastdfs
           

檢視鏡像

[[email protected] ~]# docker images
REPOSITORY                     TAG                 IMAGE ID            CREATED             SIZE
docker.io/morunchang/fastdfs   latest              a729ac95698a        18 months ago       460.1 MB  
           

運作tracker

docker run -d --name tracker --net=host morunchang/fastdfs sh tracker.sh
           

運作storage

docker run -d --name storage --net=host -e TRACKER_IP=<your tracker server address>:22122 -e GROUP_NAME=<group name> morunchang/fastdfs sh storage.sh

/*
  1.使用的網絡模式是–net=host, <your tracker server address> 替換為你機器的Ip即可
  2.<group name> 是組名,即storage的組,下面預設用group1
  3.如果想要增加新的storage伺服器,再次運作該指令,注意更換 新組名

  4. docker ps 檢視容器資訊 
[[email protected] ~]# docker ps 
CONTAINER ID        IMAGE                COMMAND             CREATED              STATUS              PORTS               NAMES
ccdf6bbeab48        morunchang/fastdfs   "sh storage.sh"     5 seconds ago        Up 4 seconds                            storage
a7253c93bce1        morunchang/fastdfs   "sh tracker.sh"     About a minute ago   Up About a minute                       tracker
*/
           

修改nginx的配置,不攔截上傳内容

進入storage的容器内部,修改nginx.conf

//1.進入容器内部
docker exec -it storage  /bin/bash

     // storage 是 docker ps 中的NAMES
     // exit 退出

[email protected]:/# cd data
[email protected]:/data# ls
fast_data  fastdfs  fastdfs-nginx-module  libfastcommon  nginx  nginx-1.9.11.tar.gz

//2.修改nginx配置檔案
[email protected]:/# vi /data/nginx/conf/nginx.conf

//3. 添加修改内容
location /group1/M00 {
   proxy_next_upstream http_502 http_504 error timeout invalid_header;
     proxy_cache http-cache;
     proxy_cache_valid  200 304 12h;
     proxy_cache_key $uri$is_args$args;
     proxy_pass http://fdfs_group1;
     expires 30d;
 }

//4.退出
[email protected]:/data/nginx/conf# exit
exit

//5. 重新開機storage服務
[[email protected] ~]# docker restart storage
storage
           

到這裡docker已經安裝完成。

---------------------------------------華麗的分割線-----------------------------------------------

下面是與springMVC項目內建

上傳fastdfs-client-java至nexus私有庫上,

配置項目maven的pom檔案

<dependency>
    <groupId>org.csource</groupId>
    <artifactId>fastdfs-client-java</artifactId>
    <version>1.27</version>
</dependency>
           

resources下建立fast_client.conf檔案

docker安裝fastDFS檔案存儲,并與springMVC內建

并新增以下内容

connect_timeout = 60
#網絡逾時時間
network_timeout = 60
#字元集
charset = UTF-8
#跟蹤伺服器的端口
http.tracker_http_port = 8080
http.anti_steal_token = no
http.secret_key = 123456
#跟蹤伺服器位址 。跟蹤伺服器主要是起到負載均衡的作用
tracker_server = ip:22122
           

新增工具類FastDFSUtil.java和FileUtil.java

package com.ls.common.web.utils.fastdfs; import org.csource.common.MyException; import org.csource.common.NameValuePair; import org.csource.fastdfs.*; import org.slf4j.Logger; import org.slf4j.LoggerFactory; import org.springframework.core.io.ClassPathResource; import org.springframework.web.multipart.MultipartFile; import javax.servlet.http.HttpServletResponse; import java.io.*; import java.util.HashMap; import java.util.Map; public class FastDFSUtil { private final static Logger logger = LoggerFactory.getLogger(FastDFSUtil.class); public static Map<String, Object> uploadLocalFile(String filePath) { Map<String, Object> retMap = new HashMap<String, Object>(); String command = "fdfs_upload_file /etc/fdfs/client.conf " + filePath; String fileId = ""; InputStreamReader inputStreamReader = null; BufferedReader bufferedReader = null; try { Process process = Runtime.getRuntime().exec(command); inputStreamReader = new InputStreamReader(process.getInputStream()); bufferedReader = new BufferedReader(inputStreamReader); String line; if ((line = bufferedReader.readLine()) != null) { fileId = line; } if (fileId.contains("M00")) { retMap.put("code", "0000"); retMap.put("group", fileId.substring(0, 6)); retMap.put("msg", fileId.substring(7, fileId.length())); } else { retMap.put("code", "0001"); //上傳錯誤 retMap.put("msg", fileId); //傳回資訊 } } catch (Exception e) { logger.error("IOException:" + e.getMessage()); retMap.put("code", "0002"); retMap.put("msg", e.getMessage()); }finally { if (inputStreamReader!=null){ try { inputStreamReader.close(); } catch (IOException e) { e.printStackTrace(); } } if (bufferedReader != null) { try { bufferedReader.close(); } catch (IOException e) { e.printStackTrace(); } } } return retMap; } public static Map<String, Object> upload(String filePath) { Map<String, Object> retMap = new HashMap<String, Object>(); File file = new File(filePath); TrackerServer trackerServer = null; StorageServer storageServer = null; if (file.isFile()) { try { String tempFileName = file.getName(); byte[] fileBuff = FileUtil.getBytesFromFile(file); String fileId = ""; //截取字尾 String fileExtName = tempFileName.substring(tempFileName.lastIndexOf(".") + 1); ConfigAndConnectionServer configAndConnectionServer = new ConfigAndConnectionServer().invoke(1); StorageClient1 storageClient1 = configAndConnectionServer.getStorageClient1(); storageServer = configAndConnectionServer.getStorageServer(); trackerServer = configAndConnectionServer.getTrackerServer(); NameValuePair[] metaList = new NameValuePair[3]; //原始檔案名稱 metaList[0] = new NameValuePair("fileName", tempFileName); //檔案字尾 metaList[1] = new NameValuePair("fileExtName", fileExtName); //檔案大小 metaList[2] = new NameValuePair("fileLength", String.valueOf(file.length())); //開始上傳檔案 fileId = storageClient1.upload_file1(fileBuff, fileExtName, metaList); retMap = handleResult(retMap, fileId); } catch (Exception e) { e.printStackTrace(); retMap.put("code", "0002"); retMap.put("msg", e.getMessage()); } finally { colse(storageServer, trackerServer); } } else { retMap.put("code", "0001"); retMap.put("msg", "error:本地檔案不存在!"); } return retMap; } public static Map<String, Object> upload(MultipartFile file) { Map<String, Object> retMap = new HashMap<String, Object>(); TrackerServer trackerServer = null; StorageServer storageServer = null; try { if (file.isEmpty()) { retMap.put("code", "0001"); retMap.put("msg", "error:檔案為空!"); } else { ConfigAndConnectionServer configAndConnectionServer = new ConfigAndConnectionServer().invoke(1); StorageClient1 storageClient1 = configAndConnectionServer.getStorageClient1(); storageServer = configAndConnectionServer.getStorageServer(); trackerServer = configAndConnectionServer.getTrackerServer(); String tempFileName = file.getOriginalFilename(); //設定元資訊 NameValuePair[] metaList = new NameValuePair[3]; //原始檔案名稱 metaList[0] = new NameValuePair("fileName", tempFileName); //檔案字尾 byte[] fileBuff = file.getBytes(); String fileId = ""; //截取字尾 String fileExtName = tempFileName.substring(tempFileName.lastIndexOf(".") + 1); metaList[1] = new NameValuePair("fileExtName", fileExtName); //檔案大小 metaList[2] = new NameValuePair("fileLength", String.valueOf(file.getSize())); fileId = storageClient1.upload_file1(fileBuff, fileExtName, metaList); retMap = handleResult(retMap, fileId); } } catch (Exception e) { e.printStackTrace(); retMap.put("code", "0002"); retMap.put("msg", "error:檔案上傳失敗!"); }finally { colse(storageServer, trackerServer); } return retMap; } public static void download(HttpServletResponse response, String group, String filepath, String downname) { StorageServer storageServer = null; TrackerServer trackerServer = null; try { ConfigAndConnectionServer configAndConnectionServer = new ConfigAndConnectionServer().invoke(0); StorageClient storageClient = configAndConnectionServer.getStorageClient(); storageServer = configAndConnectionServer.getStorageServer(); trackerServer = configAndConnectionServer.getTrackerServer(); byte[] b = storageClient.download_file(group, filepath); if (b == null) { logger.error("Error1 : file not Found!"); response.getWriter().write("Error1 : file not Found!"); } else { logger.info("下載下傳檔案.."); downname = new String(downname.getBytes("utf-8"), "ISO8859-1"); response.setHeader("Content-Disposition", "attachment;fileName=" + downname); OutputStream out = response.getOutputStream(); out.write(b); out.close(); } } catch (Exception e) { e.printStackTrace(); try { response.getWriter().write("Error1 : file not Found!"); } catch (IOException e1) { e1.printStackTrace(); } }finally { colse(storageServer, trackerServer); } } public static Map<String, Object> delete(String group, String filepath) { Map<String, Object> retMap = new HashMap<String, Object>(); StorageServer storageServer = null; TrackerServer trackerServer = null; try { ConfigAndConnectionServer configAndConnectionServer = new ConfigAndConnectionServer().invoke(0); StorageClient storageClient = configAndConnectionServer.getStorageClient(); storageServer = configAndConnectionServer.getStorageServer(); trackerServer = configAndConnectionServer.getTrackerServer(); int i = storageClient.delete_file(group, filepath); if (i == 0) { retMap.put("code", "0000"); retMap.put("msg", "删除成功!"); } else { retMap.put("code", "0001"); retMap.put("msg", "檔案不存在!"); } } catch (Exception e) { e.printStackTrace(); retMap.put("code", "0002"); retMap.put("msg", "删除失敗!"); } finally { colse(storageServer, trackerServer); } return retMap; } private static void colse(StorageServer storageServer, TrackerServer trackerServer) { if (storageServer != null && trackerServer != null) { try { storageServer.close(); trackerServer.close(); } catch (IOException e) { e.printStackTrace(); } } } private static Map<String, Object> handleResult(Map<String, Object> retMap, String fileId) { if (!fileId.equals("") && fileId != null) { retMap.put("code", "0000"); retMap.put("group", fileId.substring(0, 6)); retMap.put("msg", fileId.substring(7, fileId.length())); } else { retMap.put("code", "0003"); retMap.put("msg", "error:上傳失敗!"); } return retMap; } private static class ConfigAndConnectionServer { private TrackerServer trackerServer; private StorageServer storageServer; private StorageClient storageClient; private StorageClient1 storageClient1; public TrackerServer getTrackerServer() { return trackerServer; } public StorageServer getStorageServer() { return storageServer; } public StorageClient getStorageClient() { return storageClient; } public StorageClient1 getStorageClient1() { return storageClient1; } public ConfigAndConnectionServer invoke(int flag) throws IOException, MyException { ClassPathResource cpr = new ClassPathResource("fdfs_client.conf"); ClientGlobal.init(cpr.getClassLoader().getResource("fdfs_client.conf").getPath()); TrackerClient tracker = new TrackerClient(); trackerServer = tracker.getConnection(); storageServer = null; if (flag == 0) { storageClient = new StorageClient(trackerServer, storageServer); } else { storageClient1 = new StorageClient1(trackerServer, storageServer); } return this; } } }

package com.ls.common.web.utils.fastdfs;

import org.springframework.web.multipart.commons.CommonsMultipartFile;

import java.io.*;
import java.util.Date;

/**
 * FastDFS工具類
 * @author yusheng
 * @since 2018-4-28
 * @version 1.0
 */
public class FileUtil {
   
   
   public static void saveImage(CommonsMultipartFile[] files, int i) {
      if(!files[i].isEmpty()){  
          int pre = (int) System.currentTimeMillis();  
          try {  
              //拿到輸出流,同時重命名上傳的檔案  
              FileOutputStream os = new FileOutputStream("f:/img"+"/" + new Date().getTime()+".jpg");  
              //拿到上傳檔案的輸入流  
              ByteArrayInputStream in =  (ByteArrayInputStream) files[i].getInputStream();  
                
              //以寫位元組的方式寫檔案  
              int b = 0;  
              while((b=in.read()) != -1){  
                  os.write(b);  
              }  
              os.flush();  
              os.close();  
              in.close();  
              int finaltime = (int) System.currentTimeMillis();  
              System.out.println(finaltime - pre);  
                
          } catch (Exception e) {  
              e.printStackTrace();  
              System.out.println("上傳出錯");  
          }  
      }
   }


   /**
    * 擷取檔案流
    * @param f
    * @return
    */
   public static byte[] getBytesFromFile(File f){
      if (f == null) {
         return null;
      }
      try {
         FileInputStream stream = new FileInputStream(f);
         ByteArrayOutputStream out = new ByteArrayOutputStream(1000);
         byte[] b = new byte[1000];
         for (int n;(n = stream.read(b)) != -1;) {
            out.write(b, 0, n);
         }
         stream.close();
         out.close();
         return out.toByteArray();
      } catch (IOException e) {

      }
      return null;
   }

}
           

編寫測試類

@RequestMapping("/upload")
public String upload(@RequestParam("file") CommonsMultipartFile[] files,
                HttpServletRequest request){

   for(int i = 0;i<files.length;i++){
      Map<String, Object> retMap = FastDFSUtil.upload(files[i]);
      String code = (String) retMap.get("code");
      String group = (String) retMap.get("group");
      String msg = (String) retMap.get("msg");

      if ("0000".equals(code)){
         logger.info("檔案上傳成功");
         //TODO:将上傳檔案的路徑儲存到mysql資料庫
      }else {
         logger.info("檔案上傳失敗");
      }


   }
   return "/success";
}
           

傳回msg為檔案存儲路徑,測試後拼接ip端口,浏覽器通路,可以通路則內建成功。

繼續閱讀