天天看點

實戰:使用FastDFS進行檔案上傳下載下傳使用FastDFS進行檔案上傳下載下傳

使用FastDFS進行檔案上傳下載下傳

導航

  • 使用FastDFS進行檔案上傳下載下傳
    • 一. 準備
      • 1.1 引入pom依賴
      • 1.2 在resources/application.yml中配置:
      • 1.3 引入FastDFS相關的config
    • 二. 上傳
      • 2.1 測試FastDFS的相關代碼
      • 2.2 改造業務代碼
    • 三. 下載下傳
      • 3.1 Client
      • 3.2 上傳、下載下傳、删除等相關Api

一. 準備

1.1 引入pom依賴

<dependency>
	<groupId>com.github.tobato</groupId>
	<artifactId>fastdfs-client</artifactId>
	<version>${fastDFS.clent.version}</version>
</dependency> 
           
在SpringBoot内可不定義版本号,跟随SpringBoot

1.2 在resources/application.yml中配置:

fdfs:
	so-timeout:1501  # 讀取逾時時間
	connect-timeout: 601 #連接配接逾時時間
	thumb-image:  #縮略圖
		width: 60
		height: 60
	tracker-list: # tracker位址: 你的虛拟機伺服器位址+端口 (預設是22122)
		- 192.168.56.101:22122
           

1.3 引入FastDFS相關的config

@Configuration
@Import(FdfsClientConfig.class)
//解決jmx重複注冊bean的問題
@EnableMBeanExport(registration=RegistrationPolicy.IGNORE_EXISTING)
public class FastClientImporter{}
           
這裡不需要寫代碼,因為@Import引入的配置就是别人已經寫好的代碼,我們就可以不用寫東西了;第二個是為了防止Bean重複注入;

二. 上傳

2.1 測試FastDFS的相關代碼

@SpringBootTest
@RunWith(SpringRunner.class)
public class FastDFSTest{
	@Autowired
	private FastFileStorageClient storageClient;

	@Autowired
	private ThumbImageConfig thumbImageConfig;

	@Test
	public void testUpload() throws FileNotFoundException{
		//要上傳的檔案
		File file=new File("C:\\USERS\\iamge.jpg")
		//上傳并儲存圖檔,參數: 1-上傳的檔案流  2-檔案的大小  3-檔案的字尾 4-可以不管他
		StorePath storePath =this.storageClient.uploadFile(new FileInputStream(file),file.length(),"jpg",null);
		//帶分組的路徑
		System.out.println(storePath.getFullPath());		//group1/M00/00/00/xxxx.jpg
		//不帶分組的路徑
		System.out.println(storePath.getPath());		//M00/00/00/xxxx.jpg
		//我們在浏覽器内通路: 192.168.56.101/group1/M00/00/00/xxxxx.jpg
		//如果配置了域名,則可以通過域名通路,比如:image.baidu.com/group1/M00/00/00/xxxxx.jpg
	}

	//測試生成縮略圖
	@Test
	public void testUploadAndCreateThumb() throws FileNotFoundException{
		File file=new File("C:\\Users\\joedy\\Pictures\\xbx1.jpg")
		//上傳并且生成縮略圖
		StorePath storePath=this.storageClient.uploadImageAndCrtThumbImage(
			new FileInputStream(file),file.length(),"jpg",null);
		//帶分組的路徑
		System.out.println(storePath.getFullPath());
		//不帶分組的路徑
		System.out.println(storePath.getPath());
		//擷取縮略圖路徑
		String path=thumbImageConfig.getThumbImagePath(storePath.getPath());
		System.out.println(path);
	}	
}

           

2.2 改造業務代碼

@Service
public class UploadService{

	private static final List<String> CONTENT_TYPES=Arrays.asList("image/gif","image/jpeg");
	private static final Logger LOGGER= LoggerFactory.getLogger(UploadService.class);
	
	@Autowired
	private FastFileStorageClient storageClient;
	
	public String uploadImage(MutipartFile file){
		String originalFilename=file.getOriginalFilename();
		//校驗檔案類型
		String contentType=file.getContentType();
		if(!CONTENT_TYPES.contains(contentType)){
			LOGGER.info("檔案類型不合法:{}",originalFilename);		//這裡的第二個參數會自動進入{}内
			return null;
		}
		//儲存到伺服器
		//file.transferTo(new File("C:\\image\\"+originalFilename));   這裡是儲存到本地磁盤,這裡不用這個。
		String ext=StringUtils.substringAfterLast(originalFilename,".");
		StorePath storePath=this.storageClient.uploadFile(file.getInputStream(),file.getSize(),ext,null);
		//傳回url,進行回顯
		//return "http://image.baidu.com/" + originalFilename;
		return "http://image.baidu.com"+ storePath.getFullPath();
	}catch(IOException e){
		LOGGER.info("伺服器内部錯誤:"+originalFilename);
		e.printStackTrace();
	}
		return null;
}
           

三. 下載下傳

3.1 Client

import com.cdmtc.config.ErrorCode;
import com.cdmtc.config.FastDFSException;
import org.apache.commons.codec.binary.Base64;
import org.apache.commons.lang3.StringUtils;
import org.csource.common.MyException;
import org.csource.common.NameValuePair;
import org.csource.fastdfs.FileInfo;
import org.csource.fastdfs.ProtoCommon;
import org.csource.fastdfs.StorageClient1;
import org.csource.fastdfs.TrackerServer;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.security.NoSuchAlgorithmException;
import java.text.SimpleDateFormat;
import java.time.Instant;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;

/**
 * FastDFS Java API. 檔案上傳下載下傳主類.
 */
public class FastDFSClient {

    private static class SingletonHolder{
        /**
         * 靜态初始化器,由JVM來保證線程安全
         */
        private static FastDFSClient instance = new FastDFSClient();
    }
    /**
     * 路徑分隔符
     */
    public static final String SEPARATOR = "/";
    /**
     * Point
     */
    public static final String POINT = ".";
    /**
     * ContentType
     */
    public static final Map<String, String> EXT_MAPS = new HashMap<>();

    /**
     * org.slf4j.Logger
     */
    private static Logger logger = LoggerFactory.getLogger(FastDFSClient.class);
    /**
     * 檔案名稱Key
     */
    private static final String FILENAME = "filename";
    /**
     * 檔案最大的大小
     */
    private int maxFileSize = 100 * 1000 * 1000;

    public FastDFSClient() {
        initExt();
    }

    public static  FastDFSClient getInstance(){
        return SingletonHolder.instance;
    }
    private void initExt() {
        // image
        EXT_MAPS.put("png", "image/png");
        EXT_MAPS.put("gif", "image/gif");
        EXT_MAPS.put("bmp", "image/bmp");
        EXT_MAPS.put("ico", "image/x-ico");
        EXT_MAPS.put("jpeg", "image/jpeg");
        EXT_MAPS.put("jpg", "image/jpeg");
        // 壓縮檔案
        EXT_MAPS.put("zip", "application/zip");
        EXT_MAPS.put("rar", "application/x-rar");
        // doc
        EXT_MAPS.put("pdf", "application/pdf");
        EXT_MAPS.put("ppt", "application/vnd.ms-powerpoint");
        EXT_MAPS.put("xls", "application/vnd.ms-excel");
        EXT_MAPS.put("xlsx", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet");
        EXT_MAPS.put("pptx", "application/vnd.openxmlformats-officedocument.presentationml.presentation");
        EXT_MAPS.put("doc", "application/msword");
        EXT_MAPS.put("doc", "application/wps-office.doc");
        EXT_MAPS.put("docx", "application/vnd.openxmlformats-officedocument.wordprocessingml.document");
        EXT_MAPS.put("txt", "text/plain");
        // 音頻
        EXT_MAPS.put("mp4", "video/mp4");
        EXT_MAPS.put("flv", "video/x-flv");
    }

    /**
     * MultipartFile 上傳檔案
     *
     * @param file MultipartFile
     * @return 傳回上傳成功後的檔案路徑
     */
    public String uploadFileWithMultipart(MultipartFile file) throws FastDFSException {
        return upload(file, null);
    }

    /**
     * MultipartFile 上傳檔案
     *
     * @param file MultipartFile
     * @param descriptions 檔案描述
     * @return 傳回上傳成功後的檔案路徑
     */
    public String uploadFileWithMultipart(MultipartFile file, Map<String, String> descriptions) throws FastDFSException {
        return upload(file, descriptions);
    }

    /**
     * 根據指定的路徑上傳檔案
     *
     * @param filepath 檔案路徑
     * @return 傳回上傳成功後的檔案路徑
     */
    public String uploadFileWithFilepath(String filepath) throws FastDFSException {
        return upload(filepath, null);
    }

    /**
     * 根據指定的路徑上傳檔案
     *
     * @param filepath 檔案路徑
     * @param descriptions 檔案描述
     * @return 傳回上傳成功後的檔案路徑
     */
    public String uploadFileWithFilepath(String filepath, Map<String, String> descriptions) throws FastDFSException {
        return upload(filepath, descriptions);
    }

    /**
     * 上傳base64檔案
     *
     * @param base64 檔案base64
     * @return 傳回上傳成功後的檔案路徑
     */
    public String uploadFileWithBase64(String base64) throws FastDFSException {
        return upload(base64, null, null);
    }

    /**
     * 上傳base64檔案
     *
     * @param base64 檔案base64
     * @param filename 檔案名
     * @return 傳回上傳成功後的檔案路徑
     */
    public String uploadFileWithBase64(String base64, String filename) throws FastDFSException {
        return upload(base64, filename, null);
    }

    /**
     * 上傳base64檔案
     *
     * @param base64 檔案base64
     * @param filename 檔案名
     * @param descriptions 檔案描述資訊
     * @return 傳回上傳成功後的檔案路徑
     */
    public String uploadFileWithBase64(String base64, String filename, Map<String, String> descriptions) throws FastDFSException {
        return upload(base64, filename, descriptions);
    }

    /**
     * 使用 MultipartFile 上傳
     *
     * @param file MultipartFile
     * @param descriptions 檔案描述資訊
     * @return 檔案路徑
     * @throws FastDFSException file為空則抛出異常
     */
    public String upload(MultipartFile file, Map<String, String> descriptions) throws FastDFSException {
        if(file == null || file.isEmpty()){
            throw new FastDFSException(ErrorCode.FILE_ISNULL.CODE, ErrorCode.FILE_ISNULL.MESSAGE);
        }
        String path = null;
        try {
            path = upload(file.getInputStream(), file.getOriginalFilename(), descriptions);
        } catch (IOException e) {
            e.printStackTrace();
            throw new FastDFSException(ErrorCode.FILE_ISNULL.CODE, ErrorCode.FILE_ISNULL.MESSAGE);
        }
        return path;
    }

    /**
     * 根據指定的路徑上傳
     *
     * @param filepath 檔案路徑
     * @param descriptions 檔案描述
     * @return 檔案路徑
     * @throws FastDFSException 檔案路徑為空則抛出異常
     */
    public String upload(String filepath, Map<String, String> descriptions) throws FastDFSException {
        if(StringUtils.isBlank(filepath)){
            throw new FastDFSException(ErrorCode.FILE_PATH_ISNULL.CODE, ErrorCode.FILE_PATH_ISNULL.MESSAGE);
        }
        File file = new File(filepath);
        String path = null;
        try {
            InputStream is = new FileInputStream(file);
            // 擷取檔案名
            filepath = toLocal(filepath);
            String filename = filepath.substring(filepath.lastIndexOf("/") + 1);

            path = upload(is, filename, descriptions);
        } catch (FileNotFoundException e) {
            e.printStackTrace();
            throw new FastDFSException(ErrorCode.FILE_NOT_EXIST.CODE, ErrorCode.FILE_NOT_EXIST.MESSAGE);
        }

        return path;
    }

    /**
     *
     * 上傳base64檔案
     *
     * @param base64
     * @param filename 檔案名
     * @param descriptions 檔案描述資訊
     * @return 檔案路徑
     * @throws FastDFSException base64為空則抛出異常
     */
    public String upload(String base64, String filename, Map<String, String> descriptions) throws FastDFSException {
        if(StringUtils.isBlank(base64)){
            throw new FastDFSException(ErrorCode.FILE_ISNULL.CODE, ErrorCode.FILE_ISNULL.MESSAGE);
        }
        return upload(new ByteArrayInputStream(Base64.decodeBase64(base64)), filename, descriptions);
    }

    /**
     * 上傳通用方法
     *
     * @param is 檔案輸入流
     * @param filename 檔案名
     * @param descriptions 檔案描述資訊
     * @return 組名+檔案路徑,如:group1/M00/00/00/wKgz6lnduTeAMdrcAAEoRmXZPp870.jpeg
     * @throws FastDFSException
     */
    public String upload(InputStream is, String filename, Map<String, String> descriptions) throws FastDFSException {
        if(is == null){
            throw new FastDFSException(ErrorCode.FILE_ISNULL.CODE, ErrorCode.FILE_ISNULL.MESSAGE);
        }

        try {
            if(is.available() > maxFileSize){
                throw new FastDFSException(ErrorCode.FILE_OUT_SIZE.CODE, ErrorCode.FILE_OUT_SIZE.MESSAGE);
            }
        } catch (IOException e) {
            e.printStackTrace();
        }

        filename = toLocal(filename);
        // 傳回路徑
        String path = null;
        // 檔案描述
        NameValuePair[] nvps = null;
        List<NameValuePair> nvpsList = new ArrayList<>();
        // 檔案名字尾
        String suffix = getFilenameSuffix(filename);

        // 檔案名
        if (StringUtils.isNotBlank(filename)) {
            nvpsList.add(new NameValuePair(FILENAME, filename));
        }
        // 描述資訊
        if (descriptions != null && descriptions.size() > 0) {
            descriptions.forEach((key, value) -> {
                nvpsList.add(new NameValuePair(key, value));
            });
        }
        if (nvpsList.size() > 0) {
            nvps = new NameValuePair[nvpsList.size()];
            nvpsList.toArray(nvps);
        }

        TrackerServer trackerServer = TrackerServerPool.borrowObject();
        StorageClient1 storageClient = new StorageClient1(trackerServer, null);
        try {
            // 讀取流
            byte[] fileBuff = new byte[is.available()];
            is.read(fileBuff, 0, fileBuff.length);

            // 上傳
            path = storageClient.upload_file1(fileBuff, suffix, nvps);

            if(StringUtils.isBlank(path)) {
                throw new FastDFSException(ErrorCode.FILE_UPLOAD_FAILED.CODE, ErrorCode.FILE_UPLOAD_FAILED.MESSAGE);
            }

            if (logger.isDebugEnabled()) {
                logger.debug("upload file success, return path is {}", path);
            }
        } catch (IOException e) {
            e.printStackTrace();
            throw new FastDFSException(ErrorCode.FILE_UPLOAD_FAILED.CODE, ErrorCode.FILE_UPLOAD_FAILED.MESSAGE);
        } catch (MyException e) {
            e.printStackTrace();
            throw new FastDFSException(ErrorCode.FILE_UPLOAD_FAILED.CODE, ErrorCode.FILE_UPLOAD_FAILED.MESSAGE);
        } finally {
            // 關閉流
            if(is != null){
                try {
                    is.close();
                } catch (IOException e) {
                    e.printStackTrace();
                }
            }
        }
        // 返還對象
        TrackerServerPool.returnObject(trackerServer);

        return path;
    }

    /**
     * 以附件形式下載下傳檔案
     *
     * @param filepath 檔案路徑
     * @param response
     */
    public void downloadFile(String filepath, HttpServletResponse response) throws FastDFSException {
        download(filepath, null, null, response);
    }

    /**
     * 下載下傳檔案 輸出檔案
     *
     * @param filepath 檔案路徑
     * @param os 輸出流
     */
    public void downloadFile(String filepath, OutputStream os) throws FastDFSException {
        download(filepath, null, os, null);
    }

    /**
     * 以附件形式下載下傳檔案 可以指定檔案名稱.
     *
     * @param filepath 檔案路徑
     * @param filename 檔案名稱
     * @param response HttpServletResponse
     */
    public void downloadFile(String filepath, String filename, HttpServletResponse response) throws FastDFSException {
        download(filepath, filename, null, response);
    }

    /**
     * 下載下傳檔案
     *
     * @param filepath 檔案路徑
     * @param filename 檔案名稱
     * @param os 輸出流
     * @param response HttpServletResponse
     */
    public void download(String filepath, String filename, OutputStream os, HttpServletResponse response) throws FastDFSException {
        if(StringUtils.isBlank(filepath)){
            throw new FastDFSException(ErrorCode.FILE_PATH_ISNULL.CODE, ErrorCode.FILE_PATH_ISNULL.MESSAGE);
        }

        filepath = toLocal(filepath);
        // 檔案名
        if (StringUtils.isBlank(filename)) {
            filename = getOriginalFilename(filepath);
        }
        String contentType = EXT_MAPS.get(getFilenameSuffix(filename));

        if(logger.isDebugEnabled()){
            logger.debug("download file, filepath = {}, filename = {}", filepath, filename);
        }

        TrackerServer trackerServer = TrackerServerPool.borrowObject();
        StorageClient1 storageClient = new StorageClient1(trackerServer, null);
        InputStream is = null;
        try {
            // 下載下傳
            byte[] fileByte = storageClient.download_file1(filepath);

            if(fileByte == null){
                throw new FastDFSException(ErrorCode.FILE_NOT_EXIST.CODE, ErrorCode.FILE_NOT_EXIST.MESSAGE);
            }

            if (response != null) {
                os = response.getOutputStream();

                // 設定響應頭
                if (StringUtils.isNotBlank(contentType)) {
                    // 檔案編碼 處理檔案名中的 '+'、' ' 特殊字元
                    String encoderName = URLEncoder.encode(filename, "UTF-8").replace("+", "%20").replace("%2B", "+");
                    response.setHeader("Content-Disposition", "attachment;filename=\"" + encoderName + "\"");
                    response.setContentType(contentType + ";charset=UTF-8");
                    response.setHeader("Accept-Ranges", "bytes");
                }
            }

            is = new ByteArrayInputStream(fileByte);
            byte[] buffer = new byte[1024 * 5];
            int len = 0;
            while ((len = is.read(buffer)) > 0) {
                os.write(buffer, 0, len);
            }
            os.flush();
        } catch (IOException e) {
            e.printStackTrace();
        } catch (MyException e) {
            e.printStackTrace();
            throw new FastDFSException(ErrorCode.FILE_DOWNLOAD_FAILED.CODE, ErrorCode.FILE_DOWNLOAD_FAILED.MESSAGE);
        } finally {
            // 關閉流
            try {
                if(is != null){
                    is.close();
                }
                if(os != null){
                    os.close();
                }
            } catch (IOException e) {
                e.printStackTrace();
            }
        }
        // 返還對象
        TrackerServerPool.returnObject(trackerServer);
    }

    /**
     * 下載下傳檔案
     *
     * @param filepath 檔案路徑
     * @return 傳回檔案位元組
     * @throws FastDFSException
     */
    public byte[] download(String filepath) throws FastDFSException {
        logger.info("下載下傳檔案路徑:"+filepath);
        if(StringUtils.isBlank(filepath)){
            throw new FastDFSException(ErrorCode.FILE_PATH_ISNULL.CODE, ErrorCode.FILE_PATH_ISNULL.MESSAGE);
        }

        TrackerServer trackerServer = TrackerServerPool.borrowObject();
        StorageClient1 storageClient = new StorageClient1(trackerServer, null);
        InputStream is = null;
        byte[] fileByte = null;
        try {
            fileByte = storageClient.download_file1(filepath);

            if(fileByte == null){
                throw new FastDFSException(ErrorCode.FILE_NOT_EXIST.CODE, ErrorCode.FILE_NOT_EXIST.MESSAGE);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (MyException e) {
            e.printStackTrace();
            throw new FastDFSException(ErrorCode.FILE_DOWNLOAD_FAILED.CODE, ErrorCode.FILE_DOWNLOAD_FAILED.MESSAGE);
        }
        // 返還對象
        TrackerServerPool.returnObject(trackerServer);

        return fileByte;
    }

    /**
     * 删除檔案
     *
     * @param filepath 檔案路徑
     * @return 删除成功傳回 0, 失敗傳回其它
     */
    public int deleteFile(String filepath) throws FastDFSException {
        if(StringUtils.isBlank(filepath)){
            throw new FastDFSException(ErrorCode.FILE_PATH_ISNULL.CODE, ErrorCode.FILE_PATH_ISNULL.MESSAGE);
        }

        TrackerServer trackerServer = TrackerServerPool.borrowObject();
        StorageClient1 storageClient = new StorageClient1(trackerServer, null);
        int success = 0;
        try {
            success = storageClient.delete_file1(filepath);
            if(success != 0){
                throw new FastDFSException(ErrorCode.FILE_DELETE_FAILED.CODE, ErrorCode.FILE_DELETE_FAILED.MESSAGE);
            }
        } catch (IOException e) {
            e.printStackTrace();
        } catch (MyException e) {
            e.printStackTrace();
            throw new FastDFSException(ErrorCode.FILE_DELETE_FAILED.CODE, ErrorCode.FILE_DELETE_FAILED.MESSAGE);
        }
        // 返還對象
        TrackerServerPool.returnObject(trackerServer);

        return success;
    }

    /**
     * 擷取檔案資訊
     * 
     * @param filepath 檔案路徑
     * @return 檔案資訊
     * 
     * <pre>
     *  {<br>
     *      "SourceIpAddr": 源IP <br>
     *      "FileSize": 檔案大小 <br>
     *      "CreateTime": 建立時間 <br>
     *      "CRC32": 簽名 <br>
     *  }  <br>
     * </pre>
     */
    public Map<String, Object> getFileInfo(String filepath) throws FastDFSException {
        TrackerServer trackerServer = TrackerServerPool.borrowObject();
        StorageClient1 storageClient = new StorageClient1(trackerServer, null);
        FileInfo fileInfo = null;
        try {
            fileInfo = storageClient.get_file_info1(filepath);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (MyException e) {
            e.printStackTrace();
        }
        // 返還對象
        TrackerServerPool.returnObject(trackerServer);

        Map<String, Object> infoMap = new HashMap<>(4);

        infoMap.put("SourceIpAddr", fileInfo.getSourceIpAddr());
        infoMap.put("FileSize", fileInfo.getFileSize());
        infoMap.put("CreateTime", new SimpleDateFormat("yyyy-MM-dd HH:mm:ss").format(fileInfo.getCreateTimestamp()));
        infoMap.put("CRC32", fileInfo.getCrc32());

        return infoMap;
    }

    /**
     * 擷取檔案描述資訊
     * 
     * @param filepath 檔案路徑
     * @return 檔案描述資訊
     */
    public Map<String, Object> getFileDescriptions(String filepath) throws FastDFSException {
        TrackerServer trackerServer = TrackerServerPool.borrowObject();
        StorageClient1 storageClient = new StorageClient1(trackerServer, null);
        NameValuePair[] nvps = null;
        try {
            nvps = storageClient.get_metadata1(filepath);
        } catch (IOException e) {
            e.printStackTrace();
        } catch (MyException e) {
            e.printStackTrace();
        }
        // 返還對象
        TrackerServerPool.returnObject(trackerServer);

        Map<String, Object> infoMap = null;

        if (nvps != null && nvps.length > 0) {
            infoMap = new HashMap<>(nvps.length);

            for (NameValuePair nvp : nvps) {
                infoMap.put(nvp.getName(), nvp.getValue());
            }
        }

        return infoMap;
    }

    /**
     * 擷取源檔案的檔案名稱
     * 
     * @param filepath 檔案路徑
     * @return 檔案名稱
     */
    public String getOriginalFilename(String filepath) throws FastDFSException {
        Map<String, Object> descriptions = getFileDescriptions(filepath);
        if (descriptions != null && descriptions.get(FILENAME) != null) {
            return (String) descriptions.get(FILENAME);
        }
        return null;
    }

    /**
     * 擷取檔案名稱的字尾
     *
     * @param filename 檔案名 或 檔案路徑
     * @return 檔案字尾
     */
    public static String getFilenameSuffix(String filename) {
        String suffix = null;
        String originalFilename = filename;
        if (StringUtils.isNotBlank(filename)) {
            if (filename.contains(SEPARATOR)) {
                filename = filename.substring(filename.lastIndexOf(SEPARATOR) + 1);
            }
            if (filename.contains(POINT)) {
                suffix = filename.substring(filename.lastIndexOf(POINT) + 1);
            } else {
                if (logger.isErrorEnabled()) {
                    logger.error("filename error without suffix : {}", originalFilename);
                }
            }
        }
        return suffix;
    }

    /**
     * 轉換路徑中的 '\' 為 '/' <br>
     * 并把檔案字尾轉為小寫
     *
     * @param path 路徑
     * @return
     */
    public static String toLocal(String path) {
        if (StringUtils.isNotBlank(path)) {
            path = path.replaceAll("\\\\", SEPARATOR);

            if (path.contains(POINT)) {
                String pre = path.substring(0, path.lastIndexOf(POINT) + 1);
                String suffix = path.substring(path.lastIndexOf(POINT) + 1).toLowerCase();
                path = pre + suffix;
            }
        }
        return path;
    }

    /**
     * 擷取FastDFS檔案的名稱,如:M00/00/00/wKgzgFnkTPyAIAUGAAEoRmXZPp876.jpeg
     *
     * @param fileId 包含組名和檔案名,如:group1/M00/00/00/wKgzgFnkTPyAIAUGAAEoRmXZPp876.jpeg
     * @return FastDFS 傳回的檔案名:M00/00/00/wKgzgFnkTPyAIAUGAAEoRmXZPp876.jpeg
     */
    public static String getFilename(String fileId){
        String[] results = new String[2];
        StorageClient1.split_file_id(fileId, results);

        return results[1];
    }

    /**
     * 擷取通路伺服器的token,拼接到位址後面
     *
     * @param filepath 檔案路徑 group1/M00/00/00/wKgzgFnkTPyAIAUGAAEoRmXZPp876.jpeg
     * @param httpSecretKey 秘鑰
     * @return 傳回token,如: token=078d370098b03e9020b82c829c205e1f&ts=1508141521
     */
    public static String getToken(String filepath, String httpSecretKey){
        // unix seconds
        int ts = (int) Instant.now().getEpochSecond();
        // token
        String token = "null";
        try {
            token = ProtoCommon.getToken(getFilename(filepath), ts, httpSecretKey);
        } catch (UnsupportedEncodingException e) {
            e.printStackTrace();
        } catch (NoSuchAlgorithmException e) {
            e.printStackTrace();
        } catch (MyException e) {
            e.printStackTrace();
        }

        StringBuilder sb = new StringBuilder();
        sb.append("token=").append(token);
        sb.append("&ts=").append(ts);

        return sb.toString();
    }

    /**
     * @return the max file size
     */
    public int getMaxFileSize() {
        return maxFileSize;
    }

    /**
     * Set max file size, default 100M
     * @param maxFileSize the max file size
     */
    public void setMaxFileSize(int maxFileSize) {
        this.maxFileSize = maxFileSize;
    }
}
           

3.2 上傳、下載下傳、删除等相關Api

import com.cdmtc.common.FastDFSClient;
import com.cdmtc.config.ErrorCode;
import com.cdmtc.config.FastDFSException;
import com.cdmtc.config.FileResponseData;
import com.cdmtc.utils.FileCheck;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.context.annotation.PropertySource;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;

import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.IOException;

/**
 * 檔案接口
 */
@RestController
@RequestMapping("web/fastdfs/file")
@PropertySource("classpath:config.properties")
@Api(value = "FileObjectController",tags = {"檔案接口"})
public class FileObjectController {

    /**
     * 檔案伺服器位址
     */
    @Value("${file_server_addr}")
    private String fileServerAddr;
    /**
     * http位址
     */
    @Value("${fastdfs.httpServerAddr}")
    private String httpServerAddr;
    /**
     * FastDFS秘鑰
     */
    @Value("${fastdfs.http_secret_key}")
    private String fastDFSHttpSecretKey;

    /**
     * 上傳檔案通用,隻上傳檔案到伺服器,不會儲存記錄到資料庫
     *
     * @param file
     * @param request
     * @return 傳回檔案路徑等資訊
     */
    @PostMapping(value = "/upload")
    @ApiOperation(value = "上傳檔案通用")
    public FileResponseData uploadFileSample(MultipartFile file, HttpServletRequest request){
//    	System.out.println(httpServerAddr);
        return uploadSample(file, request);
    }

    /**
     * 隻能上傳圖檔,隻上傳檔案到伺服器,不會儲存記錄到資料庫. <br>
     * 會檢查檔案格式是否正确,預設隻能上傳 ['png', 'gif', 'jpeg', 'jpg'] 幾種類型.
     *
     * @param file
     * @param request
     * @return 傳回檔案路徑等資訊
     */
    @PostMapping("/upload/image")
    @ApiOperation(value = "隻能上傳圖檔")
    public FileResponseData uploadImageSample(@RequestParam MultipartFile file, HttpServletRequest request){
        // 檢查檔案類型
        if(!FileCheck.checkImage(file.getOriginalFilename())){
            FileResponseData responseData = new FileResponseData(false);
            responseData.setCode(ErrorCode.FILE_TYPE_ERROR_IMAGE.CODE);
            responseData.setMessage(ErrorCode.FILE_TYPE_ERROR_IMAGE.MESSAGE);
            return responseData;
        }

        return uploadSample(file, request);
    }

    /**
     * 隻能上傳文檔,隻上傳檔案到伺服器,不會儲存記錄到資料庫. <br>
     * 會檢查檔案格式是否正确,預設隻能上傳 ['pdf', 'ppt', 'xls', 'xlsx', 'pptx', 'doc', 'docx'] 幾種類型.
     *
     * @param file
     * @param request
     * @return 傳回檔案路徑等資訊
     */
    @PostMapping("/upload/doc")
    @ApiOperation(value = "隻能上傳文檔")
    public FileResponseData uploadDocSample(@RequestParam MultipartFile file, HttpServletRequest request){
        // 檢查檔案類型
        if(!FileCheck.checkDoc(file.getOriginalFilename())){
            FileResponseData responseData = new FileResponseData(false);
            responseData.setCode(ErrorCode.FILE_TYPE_ERROR_DOC.CODE);
            responseData.setMessage(ErrorCode.FILE_TYPE_ERROR_DOC.MESSAGE);
            return responseData;
        }

        return uploadSample(file, request);
    }

    /**
     * 以附件形式下載下傳檔案
     *
     * @param filePath 檔案位址
     * @param response
     */
    @PostMapping("/download")
    @ApiOperation(value = "以附件形式下載下傳檔案")
    public void downloadFile(String filePath, HttpServletResponse response) throws FastDFSException {
        try {
            FastDFSClient.getInstance().downloadFile(filePath, response);
        } catch (FastDFSException e) {
            e.printStackTrace();
            throw e;
        }
    }

    /**
     * 擷取圖檔 使用輸出流輸出位元組碼,可以使用< img>标簽顯示圖檔<br>
     *
     * @param filePath 圖檔位址
     * @param response
     */
    @PostMapping("/download/image")
    @ApiOperation(value = "擷取圖檔可以使用< img>标簽顯示圖檔")
    public void downloadImage(String filePath, HttpServletResponse response) throws FastDFSException {
        try {
            FastDFSClient.getInstance().downloadFile(filePath, response.getOutputStream());
        } catch (FastDFSException e) {
            e.printStackTrace();
            throw e;
        } catch (IOException e) {
            e.printStackTrace();
        }
    }

    /**
     * 根據指定的路徑删除伺服器檔案,适用于沒有儲存資料庫記錄的檔案
     *
     * @param filePath
     */
    @PostMapping("/delete")
    @ApiOperation(value = "據指定的路徑删除伺服器檔案")
    public FileResponseData deleteFile(@RequestParam(value = "filePath")String filePath) {
        FileResponseData responseData = new FileResponseData();
        try {
            FastDFSClient.getInstance().deleteFile(filePath);
        } catch (FastDFSException e) {
            e.printStackTrace();
            responseData.setSuccess(false);
            responseData.setCode(e.getCode());
            responseData.setMessage(e.getMessage());
        }
        return responseData;
    }

    /**
     * 擷取通路檔案的token
     *
     * @param filePath 檔案路徑
     * @return
     */
    @PostMapping("/get/token")
    @ApiOperation(value = "擷取通路檔案的token")
    public FileResponseData getToken(String filePath){
        FileResponseData responseData = new FileResponseData();
        // 設定訪檔案的Http位址. 有時效性.
        String token = FastDFSClient.getInstance().getToken(filePath, fastDFSHttpSecretKey);
        responseData.setToken(token);
        responseData.setHttpUrl(httpServerAddr+"/"+filePath+"?"+token);

        return responseData;
    }

    /**
     * 上傳通用方法,隻上傳到伺服器,不儲存記錄到資料庫
     *
     * @param file
     * @param request
     * @return
     */
    public FileResponseData uploadSample(MultipartFile file, HttpServletRequest request){
        FileResponseData responseData = new FileResponseData();
        try {
            // 上傳到伺服器
            String filepath = FastDFSClient.getInstance().uploadFileWithMultipart(file);

            responseData.setFileName(file.getOriginalFilename());
            responseData.setFilePath(filepath);
            responseData.setFileType(FastDFSClient.getInstance().getFilenameSuffix(file.getOriginalFilename()));
            // 設定訪檔案的Http位址. 有時效性.
            String token = FastDFSClient.getInstance().getToken(filepath, fastDFSHttpSecretKey);
            responseData.setToken(token);
            responseData.setHttpUrl(httpServerAddr+"/"+filepath+"?"+token);
        } catch (FastDFSException e) {
            responseData.setSuccess(false);
            responseData.setCode(e.getCode());
            responseData.setMessage(e.getMessage());
        }
        return responseData;
    }

}
           
若有運作不成功,遇到問題、缺少jar包依賴等可能的問題,請評論告訴我,會第一時間進行解答。