Guns二次開發(二):替換Guns自帶的圖片上傳接口

 

關於博客中使用的Guns版本問題請先閱讀   Guns二次開發目錄       

       

       因爲Guns v5.1-final 自帶的圖片上傳接口,是將上傳的圖片保存到一個指定的文件夾中,而我的項目架構中單獨搭建了FastDFS文件服務器來統一管理文件,所以就需要將Guns原來的圖片上傳接口的內部實現邏輯進行修改。又或者你僅僅只是想要修改圖片保存的位置,此時如何去找到修改點並改動別人的代碼,對於一些剛剛參加工作的開發者來說,也會很頭疼。畢竟,以我的經驗來說,即便是自己寫的代碼,時間久了也會忘記,更何況是去改動別人的代碼。鑑於此,下面我將以一個第一次接觸Guns的新手這個身份,來帶領大家,如何一步步找到修改點並修改Guns原生的代碼,進而實現本篇博客標題中的需求。閱讀這篇博客的時候,我希望大家將更多的關注點放在修改的過程和思路中,而不僅僅只是關注結果。這對你以後到了新公司,接手別人的代碼,並且因爲新的業務需求或者修改bug而不得不去改動前人的代碼時會有幫助。下面是具體的步驟:

 

第一步:找到Guns自帶的圖片上傳接口

 

 

 

 

第二步:Guns項目中引入FastDFS的Java客戶端實現代碼

 FastDFS文件服務器的搭建過程此處我就不講解了,因爲並非本篇博客的主題,這篇博客的前提條件是我已經搭建好了FastDFS服務器和前臺的項目中已經實現了FastDFS的客戶端的,所以,在Guns二次開發的時候,我直接從其它項目將FastDFS的Java客戶端實現代碼扣到guns中來,以下是具體的代碼。

 

1、添加pom依賴

<!-- FastDfs 開始-->
<!-- https://mvnrepository.com/artifact/com.luhuiguo/fastdfs-spring-boot-starter -->
<dependency>
    <groupId>com.github.tobato</groupId>
    <artifactId>fastdfs-client</artifactId>
    <version>1.26.2</version>
    <!-- 出現日誌相關異常時取消以下注釋 -->
    <!-- <exclusions>
        <exclusion>
            <groupId>ch.qos.logback</groupId>
            <artifactId>logback-classic</artifactId>
        </exclusion>
    </exclusions> -->
</dependency>
<!-- FastDfs 結束-->

 

 

2、application.yml文件中添加配置

####### FastDFS相關配置開始 #######
fdfs:
  ## tracker地址,多個可fdfs.trackerList[0]、fdfs.trackerList[1]等方式配置
  tracker-list: 192.168.0.115:22122
  ## 連接超時時間
  connect-timeout: 5000
  ## 讀取inputsream阻塞時間
  so-timeout: 3000

  pool:
    ## 連接池最大數量
    max-total: 200
    ## 每個tracker地址的最大連接數
    max-total-per-key: 50
    ## 連接耗盡時等待獲取連接的最大毫秒數
    max-wait-millis: 5000

  ## 縮略圖相關配置
  thumbImage:
    height: 150
    width: 150

####### FastDFS相關配置結束 #######

 

注意這個配置信息,要儘量放在guns的application.yml文件的公共配置信息的位置,否則不會生效。

 

3、FastDFS的java客戶端代碼

 

FastDFSClientWrapper.java

package cn.stylefeng.guns.elephish.utils.fastdfs;

import com.github.tobato.fastdfs.domain.StorePath;
import com.github.tobato.fastdfs.domain.ThumbImageConfig;
import com.github.tobato.fastdfs.proto.storage.DownloadCallback;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import org.apache.commons.io.FileUtils;
import org.apache.commons.io.FilenameUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;

import java.io.ByteArrayInputStream;
import java.io.File;
import java.io.IOException;
import java.io.InputStream;
import java.nio.charset.Charset;

/**
 * FastDFS文件上傳下載包裝類
 */
@Component
public class FastDFSClientWrapper {

    @Autowired
    private FastFileStorageClient storageClient;

    @Autowired
    private ThumbImageConfig thumbImageConfig;

    /**
     * @Description: 上傳文件
     * @param file 文件對象
     * @return 文件路徑
     * @throws IOException String
     */
    public String uploadFile(MultipartFile file) throws IOException {
        StorePath storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(),
                FilenameUtils.getExtension(file.getOriginalFilename()), null);
        return storePath.getFullPath();
    }

    /**
     * @Description: 上傳文件
     * @param bytes 文件數據
     * @param format 文件格式(後綴)
     * @return String 文件路徑
     */
    public String uploadFile(byte[] bytes, String format) {
        StorePath storePath = storageClient.uploadFile(new ByteArrayInputStream(bytes), bytes.length, format, null);
        return storePath.getFullPath();
    }

    /**
     * @Description: 上傳文件
     * @param file 文件對象
     * @return
     * @throws IOException String
     */
    public String uploadFile(File file) throws IOException {
        StorePath storePath = storageClient.uploadFile(FileUtils.openInputStream(file), file.length(),
                FilenameUtils.getExtension(file.getName()), null);
        return storePath.getFullPath();
    }

    /**
     * @Description: 把字符串作爲指定格式的文件上傳
     * @param content
     * @param fileExtension
     * @return String
     */
    public String uploadFile(String content, String fileExtension) {
        byte[] buff = content.getBytes(Charset.forName("UTF-8"));
        ByteArrayInputStream stream = new ByteArrayInputStream(buff);
        StorePath storePath = storageClient.uploadFile(stream, buff.length, fileExtension, null);
        return storePath.getFullPath();
    }

    /**
     * @Description: 上傳文件
     * @param file 文件對象
     * @return 文件路徑
     * @throws IOException String
     */
    public String uploadImageAndCrtThumbImage(MultipartFile file) throws IOException {
        StorePath storePath = storageClient.uploadImageAndCrtThumbImage(file.getInputStream(), file.getSize(),
                FilenameUtils.getExtension(file.getOriginalFilename()), null);
        return storePath.getFullPath();
    }

    /**
     * @Description: 根據圖片路徑獲取縮略圖路徑(使用uploadImageAndCrtThumbImage方法上傳圖片)
     * @param filePath 圖片路徑
     * @return String 縮略圖路徑
     */
    public String getThumbImagePath(String filePath) {
        return thumbImageConfig.getThumbImagePath(filePath);
    }

    /**
     * @Description: 根據文件路徑下載文件
     * @param filePath 文件路徑
     * @return 文件字節數據
     * @throws IOException byte[]
     */
    public byte[] downFile(String filePath) throws IOException {
        StorePath storePath = StorePath.praseFromUrl(filePath);
        return storageClient.downloadFile(storePath.getGroup(), storePath.getPath(), new DownloadCallback<byte[]>() {
            @Override
            public byte[] recv(InputStream ins) throws IOException {
                return org.apache.commons.io.IOUtils.toByteArray(ins);
            }
        });
    }

    /**
     * @Description: 根據文件地址刪除文件
     * @param filePath 文件訪問地址
     */
    public void deleteFile(String filePath) {
        StorePath storePath = StorePath.praseFromUrl(filePath);
        storageClient.deleteFile(storePath.getGroup(), storePath.getPath());
    }
}

 

 

FastDFSConfiguration.java

package cn.stylefeng.guns.elephish.utils.fastdfs;

import com.github.tobato.fastdfs.FdfsClientConfig;
import org.springframework.context.annotation.Configuration;
import org.springframework.context.annotation.EnableMBeanExport;
import org.springframework.context.annotation.Import;
import org.springframework.jmx.support.RegistrationPolicy;

/**
 * FastDFS的相關配置
 */
@Configuration
@Import(FdfsClientConfig.class)
@EnableMBeanExport(registration= RegistrationPolicy.IGNORE_EXISTING)// 解決jmx重複註冊bean的問題
public class FastDFSConfiguration {
}

 

 

FileType.java

package cn.stylefeng.guns.elephish.utils.fastdfs;


import org.apache.commons.lang3.StringUtils;

/**
 * 定義了用戶允許上傳的文件類型
 * @ClassName: FileType
 * @author hqq
 * @date 2019年4月4日
 * 
 */

public enum FileType {
	JPG("image/jpeg", "jpg")
	,PNG("image/png","png")
//	,PDF("application/pdf","pdf")
//	,TXT("text/plain","txt")
//	,DOC("application/msword","doc")
//	,DOCX("application/vnd.openxmlformats-officedocument.wordprocessingml.document","docx")
//	,XLS("application/vnd.ms-excel","xls")
//	,XLS2("application/octet-stream","xls")
//	,XLSM("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","xlsm")
//	,XLSX("application/vnd.openxmlformats-officedocument.spreadsheetml.sheet","xlsx")
	;
	
	//屬性
	private String contentType;
	private String suffix;

	// 構造方法
	private FileType(String contentType,String suffix ){
		this.contentType=contentType;
		this.suffix=suffix;
	}

	/**
	 * 傳入contentType,獲取後綴名
	 * @param contentType 
	 * @return 返回對應的後綴名,沒有值就返回null
	 */
	public static String getSuffix(String contentType){
		if(StringUtils.isBlank(contentType)){
			return null;
		}
		for(FileType tf:FileType.values()){
			if(StringUtils.endsWithIgnoreCase(contentType,tf.getContentType())){
				return tf.getSuffix();
			}
		}
		return null;
	}
	
	public String getContentType() {
		return contentType;
	}

	public void setContentType(String contentType) {
		this.contentType = contentType;
	}

	public String getSuffix() {
		return suffix;
	}

	public void setSuffix(String suffix) {
		this.suffix = suffix;
	}

}

 

 

4、修改Guns自帶的圖片上傳接口【/mgr/upload】的內部邏輯

@RequestMapping(method = RequestMethod.POST, path = "/upload")
@ResponseBody
public String upload(@RequestPart("file")MultipartFile file) {

    try{
        // 判斷文件類型
        String suffix = FileType.getSuffix(file.getContentType());
//          logger.info("文件類型:"+suffix);
        if (suffix == null) {
//                logger.info("暫不支持當前類型的文件上傳:"+suffix);
            throw new ServiceException(BizExceptionEnum.UPLOAD_ERROR);
        }

        String fileUri = fastDFSClientWrapper.uploadFile(file.getBytes(),suffix);

        //fastdfs服務器的域名
        String prefix = "http://192.168.0.115/";

        return prefix+fileUri;

    }catch (Exception e){
        throw new ServiceException(BizExceptionEnum.UPLOAD_ERROR);
    }

}

 

5、重啓Guns項目測試

 

 

 

 

第三步:修改前端頁面的圖片顯示路徑

 

 

 

修改後的文件內容:

 

 

重啓服務器:

 

至此,功能實現!

 

該系列更多文章請前往 Guns二次開發目錄

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章