Spring Boot整合FastDFS,开启token防盗链

FastDFS部署参考这里

FastDFS_Client使用

添加依赖

FastDFS_Client:项目地址
Simplemagic:项目地址
pom.xml中添加:

        <dependency>
            <groupId>com.github.tobato</groupId>
            <artifactId>fastdfs-client</artifactId>
            <version>1.27.2</version>
        </dependency>
         <dependency>
            <groupId>com.j256.simplemagic</groupId>
            <artifactId>simplemagic</artifactId>
            <version>1.16</version>
        </dependency>

添加配置类

新建FastDFSConfig.java

@Configuration
@Import(FdfsClientConfig.class)
//解决jmx重复注册bean的问题
@EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)
public class FastDFSConfig {
    // 导入依赖组件
}

修改配置文件

application.properties后面添加:

# 连接超时时长
fdfs.so-timeout = 1501
fdfs.connect-timeout = 601
# traker服务的访问地址,有多个时用逗号隔开
fdfs.tracker-list = tracker1IP:tracker1Port,tracker2IP:tracker2Port

新建FastDFS工具类

新建FastDFSUtils.java

@Slf4j
@Component
public class FastDFSUtils {
    @Autowired
    private FastFileStorageClient fastFileStorageClient;

    //文件上传
    public String uploadFile(MultipartFile file) throws Exception {
        log.info("开始上传文件至FastDFS:{}", file.getName());
        byte[] bytes;
        try {
            bytes = file.getBytes();
        } catch (IOException e) {
            log.error("读取文件错误");
            throw new Exception("读取文件错误");
        }
        //获取源文件名称
        String originalFileName = file.getOriginalFilename();
        //获取文件后缀
        String extension = originalFileName.substring(originalFileName.lastIndexOf(".") + 1);
        //获取文件大小
        long fileSize = file.getSize();
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        StorePath storePath = fastFileStorageClient.uploadFile(byteArrayInputStream, fileSize, extension, null);
        log.info("文件上传至FastDFS成功path:{}", storePath.getFullPath());

        return storePath.getFullPath();
    }
    
	//文件上传(本地文件)
    public String uploadFile(File file) throws Exception {
        log.info("开始上传文件至FastDFS:{}", file.getName());
        byte[] bytes;
        InputStream inputStream = null;
        try {
            inputStream = openInputStream(file);
            bytes = IOUtils.toByteArray(inputStream, file.length());
        } catch (IOException e) {
            log.error("读取文件错误");
            //关闭输入流
            IOUtils.closeQuietly(inputStream);
            throw new Exception("读取文件错误");
        }
        //获取源文件名称
        String fileName = file.getName();
        //获取文件后缀
        String extension = fileName.substring(fileName.lastIndexOf(".") + 1);
        //获取文件大小
        long fileSize = file.length();
        ByteArrayInputStream byteArrayInputStream = new ByteArrayInputStream(bytes);
        StorePath storePath = fastFileStorageClient.uploadFile(byteArrayInputStream, fileSize, extension, null);
        log.info("文件上传至FastDFS成功path:{}", storePath.getFullPath());

        //关闭输入流
        IOUtils.closeQuietly(inputStream);
        return storePath.getFullPath();
    }

    //文件转输入流
    public static FileInputStream openInputStream(File file) throws IOException {
        if (file.exists()) {
            if (file.isDirectory()) {
                throw new IOException("文件" + file + "'是一个目录");
            }
            if (!file.canRead()) {
                throw new IOException("文件" + file + "无法读取");
            }
        } else {
            throw new FileNotFoundException("文件" + file + "不存在");
        }
        return new FileInputStream(file);
    }

    /**
     * 文件下载
     *
     * @param fileUrl  示例:group1/M00/00/00/oYYBAF6ZsvCAaQzIAABdreSfEnY579.jpg
     */
    public void downloadFile(String fileUrl, HttpServletResponse response) throws Exception {
        //设置ContentType
        response.setContentType(getContentType(fileUrl));
        //设置keep-alive
        response.setHeader("Connection", "keep-alive");
        ServletOutputStream outputStream;
        try {
            //刷新缓冲
            response.flushBuffer();
            //获取输出流
            outputStream = response.getOutputStream();
        } catch (IOException e) {
            log.error("获取输出流异常", e);
            throw new Exception("获取输出流异常");
        }
        //解析url
        StorePath storePath = StorePath.parseFromUrl(fileUrl);
        //下载文件
        DownloadFileStream downloadFileStream = new DownloadFileStream(outputStream);
        fastFileStorageClient.downloadFile(storePath.getGroup(), storePath.getPath(), downloadFileStream);
        //关闭输出流
        IOUtils.closeQuietly(outputStream);
    }

    /**
     * 文件删除
     *
     * @param fileUrl 示例:group1/M00/00/00/oYYBAF6ZsvCAaQzIAABdreSfEnY579.jpg
     */
    public void deleteFile(String fileUrl) {
        log.info("删除FastFDS文件:{}", fileUrl);
        fastFileStorageClient.deleteFile(fileUrl);
    }

    /**
     * 下载文件时获取ContentType
     *
     * @param fileName 文件名中包含后缀即可
     */
    public String getContentType(String fileName) {
        ContentInfo contentInfo = ContentInfoUtil.findExtensionMatch(fileName);
        if (contentInfo == null) {
            return null;
        }
        return contentInfo.getMimeType();
    }
}

Controller参考代码

    @Resource
    FastDFSUtils fastDFSUtils;

	//上传文件,返回示例:group1/M00/00/00/oYYBAF6ZsvCAaQzIAABdreSfEnY579.jpg
    @ApiOperation(value = "up", notes = "")
    @RequestMapping(value = "/up", method = {RequestMethod.POST})
    public String up(MultipartFile file) {
        try {
            return fastDFSUtils.uploadFile(file);
        } catch (Exception e) {
            e.printStackTrace();
        }
        return "fail";
    }

	//下载文件,参数示例:group1/M00/00/00/oYYBAF6ZsvCAaQzIAABdreSfEnY579.jpg
    @ApiOperation(value = "down", notes = "")
    @RequestMapping(value = "/down", method = {RequestMethod.GET})
    public void down(String url, HttpServletResponse response) {
        try {
            try {
                fastDFSUtils.downloadFile(url, response);
            } catch (Exception e) {
                e.printStackTrace();
            }
        } catch (Exception e) {
            e.printStackTrace();
        }
    }

使用token防盗链

FastDFS服务器开启token防盗链,参考这里
开启token后,通过client访问文件不受影响,通过nginx访问需要添加token参数

添加依赖

pom.xml中添加:

        <dependency>
            <groupId>net.oschina.zcx7878</groupId>
            <artifactId>fastdfs-client-java</artifactId>
            <version>1.27.0.0</version>
        </dependency>

修改配置文件

application.properties后面添加:

# 开启token
fdfs.http.anti_steal_token = true
# 服务器配置的secret key
fdfs.http.secret_key = 123456
# 通过nginx访问fastDFS的地址
fdfs.web-server-url = http://yourIp:port/files/

FastDFS工具类

生成token参考代码如下:
FastDFSUtils.java中添加:

    @Value("${fdfs.web-server-url}")
    private String fastDfsUrl;

    @Value("${fdfs.http.secret_key}")
    private String fastDfsKey;
    
    /**
     * 获取带有token的访问地址
     *
     * @param fileUrl 示例:group1/M00/00/00/L2ZUml6QisqAUJE3AIOPO1HT6Bo274.mp4
     * @return java.lang.String 示例:http://yourIp:port/files/group1/M00/00/00/L2ZUml6QisqAUJE3AIOPO1HT6Bo274.mp4?token=e9a6ae7f1ecca6fed51e248c6a10d3bc&ts=1589361883
     */
    public String getTokenUrl(String fileUrl) throws Exception {
        String path = StorePath.parseFromUrl(fileUrl).getPath();
        //时间戳 单位为秒
        int ts = (int) (System.currentTimeMillis() / 1000);
        String token;
        try {
            token = ProtoCommon.getToken(path, ts, fastDfsKey);
        } catch (Exception e) {
           log.error("获取token异常", e);
           throw new Exception("FastDFS获取token异常");
        }

        return fastDfsUrl + fileUrl + "?token=" + token + "&ts=" + ts;
    }

版权声明:本文为u012784162原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。