fastDFS+SpringBoot实现文件上传和下载(防盗链)

 

 

 发布于2018-12-30 19:23:29 
 
       FastDFS内置防盗链采用Token的方式。Token是带时效的,也就是说在设定的时间范围内,比如1分钟,token是有效的。token包含了文件id、时间戳ts和密钥。
       FastDFS在URL中带上当前时间戳和带时效的token,参数名分别为ts和token。Token的生成和校验都是在服务端,因此不会存在安全问题。

例如:

http://你的IP/meng/M00/00/00/rBFE2VwohBOAOrnIAABDRU16ivg948.png?token=f48b02095128da73e43006d2b53f0001&ts=1546159147

 
一、配置文件说明

1、http.conf中防盗链相关的几个参数如下:

    # cd /etc/fdfs
    # vim /etc/fdfs/http.conf

    # if use token to anti-steal
    # default value is false (0)   
    # 是否做token检查,缺省值为false。
    http.anti_steal.check_token=true
     
    # token TTL (time to live), seconds
    # default value is 600
    # TTL,即生成token的有效时长(秒)
    http.anti_steal.token_ttl=120
     
    # secret key to generate anti-steal token
    # this parameter must be set when http.anti_steal.check_token set to true
    # the length of the secret key should not exceed 128 bytes
    # 生成token的密钥,尽量设置得长一些,千万不要泄露出去
    http.anti_steal.secret_key=FastDFS1234567890
     
    # return the content of the file when check token fail
    # default value is empty (no file sepecified)
    # 检查失败,返回的文件内容,需指定本地文件名
    http.anti_steal.token_check_fail=/home/fileError.png

需重启 tracker、storage 和 nginx

    # fdfs_trackerd /etc/fdfs/tracker.conf
    # fdfs_trackerd /etc/fdfs/tracker.conf restart
    waiting for pid [23891] exit ...
    starting ...
    # fdfs_storaged /etc/fdfs/storage.conf
    # fdfs_trackerd /etc/fdfs/tracker.conf restart
    waiting for pid [26848] exit ...
    starting ...
    # ./nginx -s reload
    ngx_http_fastdfs_set pid=26832

2、application-dev.properties

    # fastDFS
    fdfs.so-timeout=1501
    fdfs.connect-timeout=601
    fdfs.thumb-image.width=150
    fdfs.thumb-image.height=150
    fdfs.web-server-url=你的IP/
    fdfs.tracker-list[0]=你的IP:22122
    fdfs.http.anti_steal_token = true
    fdfs.http.secret_key = FastDFS1234567890

 
二、项目中增加依赖

    <!-- fastDFS -->
    <dependency>
            <groupId>com.github.tobato</groupId>
            <artifactId>fastdfs-client</artifactId>
           <version>1.26.2</version>
    </dependency>
    <dependency>
        <groupId>net.oschina.zcx7878</groupId>
        <artifactId>fastdfs-client-java</artifactId>
        <version>1.27.0.0</version>
    </dependency>

 
三、引入fastDFS配置

    import org.springframework.boot.web.servlet.MultipartConfigFactory;
    import org.springframework.context.annotation.Bean;
    import org.springframework.context.annotation.Configuration;
    import org.springframework.context.annotation.EnableMBeanExport;
    import org.springframework.context.annotation.Import;
    import org.springframework.jmx.support.RegistrationPolicy;
     
    import com.github.tobato.fastdfs.FdfsClientConfig;
     
    @Configuration
    @Import(FdfsClientConfig.class)
    @EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING)// 解决jmx重复注册bean的问题
    public class ComponetImport {
        // 导入依赖组件
    }

 
四、工具类

    import java.io.BufferedOutputStream;
    import java.io.ByteArrayInputStream;
    import java.io.ByteArrayOutputStream;
    import java.io.File;
    import java.io.FileInputStream;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.io.InputStream;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.nio.charset.Charset;
     
    import org.apache.commons.io.FilenameUtils;
    import org.apache.commons.lang.StringUtils;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.mock.web.MockMultipartFile;
    import org.springframework.stereotype.Component;
    import org.springframework.stereotype.Service;
    import org.springframework.util.Base64Utils;
    import org.springframework.web.multipart.MultipartFile;
     
    import com.github.tobato.fastdfs.conn.FdfsWebServer;
    import com.github.tobato.fastdfs.domain.StorePath;
    import com.github.tobato.fastdfs.exception.FdfsUnsupportStorePathException;
    import com.github.tobato.fastdfs.proto.storage.DownloadByteArray;
    import com.github.tobato.fastdfs.service.FastFileStorageClient;
     
     
    @Component
    public class FastDFSClient {
     
        @Autowired
        private FastFileStorageClient storageClient;
     
        @Autowired
        private FdfsWebServer fdfsWebServer;
     
        /**
         * 上传文件
         * @param file 文件对象
         * @return 文件访问地址
         * @throws IOException
         */
        public String uploadFile(MultipartFile file) throws IOException {
            StorePath storePath = storageClient.uploadFile(file.getInputStream(),file.getSize(), FilenameUtils.getExtension(file.getOriginalFilename()),null);
            return getResAccessUrl(storePath);
        }
     
        /**
         * 上传文件
         * @param file 文件对象
         * @return 文件访问地址
         * @throws IOException
         */
        public String uploadFile(File file) throws IOException {
            FileInputStream inputStream = new FileInputStream (file);
            StorePath storePath = storageClient.uploadFile(inputStream,file.length(), FilenameUtils.getExtension(file.getName()),null);
            return getResAccessUrl(storePath);
        }
     
        /**
         * 将一段字符串生成一个文件上传
         * @param content 文件内容
         * @param fileExtension
         * @return
         */
        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 getResAccessUrl(storePath);
        }
     
        // 封装图片完整URL地址
        private String getResAccessUrl(StorePath storePath) {
            String fileUrl = fdfsWebServer.getWebServerUrl() + storePath.getFullPath();
            return fileUrl;
        }
        
        /**
         * 下载文件
         * @param fileUrl 文件url
         * @return
         */
        public byte[]  download(String fileUrl) {
             String group = fileUrl.substring(0, fileUrl.indexOf("/"));
             String path = fileUrl.substring(fileUrl.indexOf("/") + 1);
             byte[] bytes = storageClient.downloadFile(group, path, new DownloadByteArray());
             return bytes;
        }
     
        /**
         * 删除文件
         * @param fileUrl 文件访问地址
         * @return
         */
        public void deleteFile(String fileUrl) {
            if (StringUtils.isEmpty(fileUrl)) {
                return;
            }
            try {
                StorePath storePath = StorePath.praseFromUrl(fileUrl);
                storageClient.deleteFile(storePath.getGroup(), storePath.getPath());
            } catch (FdfsUnsupportStorePathException e) {
                e.getMessage();
            }
        }
     
    }

 
五、文件的上传、下载 与 访问获取的 token

    import org.apache.commons.io.IOUtils;
    import org.csource.common.MyException;
    import org.csource.fastdfs.ProtoCommon;
    import org.meng.project.common.FileUtil;
    import org.meng.project.entity.Filesource;
    import org.meng.project.service.ExcelService;
    import org.meng.project.service.FileService;
    import org.meng.project.util.FastDFSClient;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.beans.factory.annotation.Value;
    import org.springframework.stereotype.Controller;
    import org.springframework.ui.Model;
    import org.springframework.web.bind.annotation.*;
    import org.springframework.web.multipart.MultipartFile;
     
    import java.io.UnsupportedEncodingException;
    import java.net.URLEncoder;
    import java.security.NoSuchAlgorithmException;
    import java.text.SimpleDateFormat;
    import java.time.Instant;
    import java.util.*;
     
    import javax.servlet.ServletOutputStream;
    import javax.servlet.http.HttpServletRequest;
    import javax.servlet.http.HttpServletResponse;
     
    @Controller
    @RequestMapping("/fdfs")
    public class FastDFSController {
        
        @Autowired
        private FastDFSClient fdfsClient;
        
        @Value("${fdfs.web-server-url}")
        private String fastdfsUrl;
        
        @Value("${fdfs.http.secret_key}")
        private String fastdfsToken;
     
        /**
         * 文件上传
         * @param file
         * @return
         * @throws Exception
         */
        @RequestMapping("/upload/file")
        @ResponseBody
        public Map<String,Object> upload(@RequestParam("file") MultipartFile file, Model model) throws Exception{
            Map<String,Object> resultMap = new HashMap<>();
            String url = null;
            
            try {
                url = fdfsClient.uploadFile(file);
                resultMap.put("code", 200);
                resultMap.put("message", "上传成功");
                resultMap.put("url", url);
                System.out.println(url);
            } catch (Exception e) {
                   // TODO: handle exception
                resultMap.put("status", 500);
                resultMap.put("message", "上传异常!");
            }
            
            return resultMap;
        }
        
        /**
         * 文件下载
         * @param fileUrl  url 开头从组名开始
         * @param response
         * @throws Exception
         */
        @RequestMapping(value="/download", method = {RequestMethod.GET})
        public void  download(HttpServletResponse response, HttpServletRequest request) throws Exception{
            String fileUrl = request.getParameter("fileUrl");
            
            byte[] data = fdfsClient.download(fileUrl);
            
            response.setCharacterEncoding("UTF-8");
            response.setHeader("Content-disposition", "attachment;filename=" + URLEncoder.encode("test.jpg", "UTF-8"));
            
            // 写出
            ServletOutputStream outputStream = response.getOutputStream();
            IOUtils.write(data, outputStream);
        }
        
        /**
         * 生成访问链接
         */
        @RequestMapping(value="/location", method = {RequestMethod.GET})
        public String location(HttpServletResponse response, HttpServletRequest request, Model model) {
            String fileUrl = request.getParameter("location");
            System.out.println(fileUrl);
            //token
            String token = fastdfsToken;
            String IP = fastdfsUrl;
            
            fileUrl = getToken(fileUrl,token,IP);
            
            model.addAttribute("Url", fileUrl);
            
            return "tools/uploadfile";
        }
        
        /**
        * 获取访问服务器的token,拼接到地址后面
        *
        * @param fid 文件路径 group1/M00/00/00/wKgzgFnkTPyAIAUGAAEoRmXZPp876.jpeg
        * @param secret_key 密钥
        * @return 返回token,如: token=078d370098b03e9020b82c829c205e1f&ts=1508141521
        */
       public static String getToken(String fid, String secret_key, String IP){
        
           String substring = fid.substring(fid.indexOf("/")+1);
           //unix时间戳 以秒为单位
           int ts = (int) (System.currentTimeMillis() / 1000);
           String token=new String();
           try {
               token= ProtoCommon.getToken(substring, ts, secret_key);
           } catch (UnsupportedEncodingException e) {
               e.printStackTrace();
           } catch (NoSuchAlgorithmException e) {
               e.printStackTrace();
           } catch (MyException e) {
               e.printStackTrace();
            }
           StringBuilder sb = new StringBuilder();
           sb.append(IP);
           sb.append(fid);
           sb.append("?token=").append(token);
           sb.append("&ts=").append(ts);
           //System.out.println(sb.toString());
           
           return sb.toString();
       }
    }

 
六、效果

1、上传

2、下载

3、获取访问链接:

访问效果图:

 

 

 

 

 

部分学习链接:

https://blog.csdn.net/qq_26545305/article/details/80186385
————————————————
版权声明:本文为CSDN博主「W_Meng_H」的原创文章,遵循 CC 4.0 BY-SA 版权协议,转载请附上原文出处链接及本声明。
原文链接:https://blog.csdn.net/W_Meng_H/article/details/85402879

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
要在Spring Boot中实现文件FastDFS,需要使用FastDFS客户端和Spring Boot的MVC框架。下面是一个基本的实现过程: 1. 添加FastDFS客户端依赖 在pom.xml文件中添加FastDFS客户端依赖,如下所示: ``` <dependency> <groupId>com.github.tobato</groupId> <artifactId>fastdfs-client</artifactId> <version>1.27.2</version> </dependency> ``` 2. 配置FastDFS客户端 在Spring Boot的配置文件application.properties中添加FastDFS客户端的配置信息,如下所示: ``` fdfs.tracker-list=192.168.1.2:22122 ``` 其中,fdfs.tracker-list表示FastDFS的Tracker服务器列表。 3. 实现文件接口 在Spring Boot的控制器中实现文件接口,如下所示: ``` @RestController public class FileUploadController { @Autowired private FastFileStorageClient storageClient; @PostMapping("/upload") public String upload(@RequestParam("file") MultipartFile file) { try { StorePath storePath = storageClient.uploadFile(file.getInputStream(), file.getSize(), FilenameUtils.getExtension(file.getOriginalFilename()), null); return storePath.getFullPath(); } catch (IOException e) { e.printStackTrace(); return "上失败"; } } } ``` 其中,@Autowired注解注入了FastDFS客户端的FastFileStorageClient对象,@PostMapping注解定义了文件接口,@RequestParam注解获取上文件。 4. 测试文件接口 可以使用Postman等工具测试文件接口,如下所示: - 请求URL:http://localhost:8080/upload - 请求方法:POST - 请求参数:file(选择要上文件) - 返回结果:成功上文件路径 以上就是基本的文件FastDFS实现过程,希望对你有所帮助。
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值