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二次开发目录

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