当前位置:网站首页>文件服务器FastDFS
文件服务器FastDFS
2022-07-26 06:55:00 【百变码农】
FastDFS可用于分布式系统环境中自行搭建文件服务器,可以达到服务器资源动静分离,请求分流的效果。本篇简单概述下其使用方法。
准备工作:
搭建springboot脚手架并成功运行,可参考历史分享springboot+mybatis
启动FastDFS服务(tracker, storage及nginx)(搭建配置FastDFS服务,后续会在运维章节另行讲述)

1. maven添加FastDFS client依赖
<dependency><groupId>com.github.tobato</groupId><artifactId>fastdfs-client</artifactId><version>1.26.7</version></dependency>
2.FastDFS配置
2.1 yml
fdfs:# 文件下载拉取地址web-server-url: https://img.xxx.comso-timeout: 3000connect-timeout: 1200thumb-image: # 缩略图width: 60height: 60tracker-list: 192.168.2.9:22122pool:jmx-enabled: false #禁止JMX重复注册,影响springboot JMX监控
2.2 FastDFS client config
import com.github.tobato.fastdfs.FdfsClientConfig;import org.springframework.boot.SpringApplication;import org.springframework.boot.autoconfigure.SpringBootApplication;import org.springframework.context.annotation.Import;@Import({FdfsClientConfig.class})@SpringBootApplicationpublic class FdfsApplication {public static void main(String[] args) {SpringApplication.run(FdfsApplication.class, args);}}
3.FastDFS使用
3.1 fdfs util
import com.github.tobato.fastdfs.domain.fdfs.StorePath;import com.github.tobato.fastdfs.exception.FdfsUnsupportStorePathException;import com.github.tobato.fastdfs.exception.FdfsUploadImageException;import com.github.tobato.fastdfs.service.FastFileStorageClient;import lombok.extern.slf4j.Slf4j;import net.coobird.thumbnailator.Thumbnails;import org.apache.commons.io.FilenameUtils;import org.apache.commons.io.IOUtils;import org.apache.commons.lang3.StringUtils;import org.springframework.web.multipart.MultipartFile;import javax.imageio.ImageIO;import java.awt.*;import java.awt.image.BufferedImage;import java.io.*;import java.util.Arrays;import java.util.List;import java.util.UUID;/*** @author Bruce* @date 2021/3/12*/@Slf4jpublic final class FdfsUtil {private static final List<String> IMAGE_TYPE = Arrays.asList("jpg", "jpeg", "png", "bmp", "tif", "gif", "webp");private static final List<String> VIDEO_TYPE = Arrays.asList("mp4", "avi");private static final String IMG_LINUX_LOCATION = "/usr/local/data/img";/*** 前端 文件上传* @param fastFileStorageClient* @param file* @param imageServer* @param needThumbnail* @param needSize* @return* @throws IOException*/public static UploadFile upload(FastFileStorageClient fastFileStorageClient, MultipartFile file, String imageServer, Byte needThumbnail, Byte needSize) throws IOException {UploadFile uploadFile = new UploadFile( file.getOriginalFilename(), file.getSize(), file.getContentType());uploadFile(fastFileStorageClient, file.getInputStream(), uploadFile, imageServer, needThumbnail, needSize);return uploadFile;}/*** 后端 文件上传* @param fastFileStorageClient* @param file* @param imageServer* @param needThumbnail* @param needSize* @return*/public static UploadFile upload(FastFileStorageClient fastFileStorageClient, File file, String imageServer, Byte needThumbnail, Byte needSize) {try (InputStream is = new FileInputStream(file)) {UploadFile uploadFile = new UploadFile( file.getName(), file.length(), null);uploadFile(fastFileStorageClient, is, uploadFile, imageServer, needThumbnail, needSize);return uploadFile;} catch (Exception e){throw new CommonException("上传文件失败", e);}}/*** 上传文件,处理图片* @param fastFileStorageClient* @param inputStream* @param uploadFile* @param imageServer* @param needThumbnail* @param needSize* @throws IOException*/private static void uploadFile(FastFileStorageClient fastFileStorageClient, InputStream inputStream, UploadFile uploadFile, String imageServer, Byte needThumbnail, Byte needSize) throws IOException {log.info("文件上传 originalFileName={}, fileSize={}", uploadFile.getOriginalFilename(), uploadFile.getFileSize());// 获取文件后缀String fileExtName = FilenameUtils.getExtension( uploadFile.getOriginalFilename()).toLowerCase();// 限制图片文件上传大小if(isSupportType(fileExtName)){validateUploadImage(uploadFile, fileExtName);}// 缓存文件流byte[] fileStream = IOUtils.toByteArray(inputStream);// 上传原图或文件uploadOrigFile(fastFileStorageClient, uploadFile, imageServer, fileStream, fileExtName);// 上传图片缩略图if(isSupportType(fileExtName)){uploadImageThumbnails(fastFileStorageClient, uploadFile, imageServer, fileStream, fileExtName, needThumbnail, needSize);}log.info("上传文件地址={}", uploadFile.getFullFilename());}/*** 限制图片文件上传大小* @param uploadFile* @param fileExtName*/private static void validateUploadImage(UploadFile uploadFile, String fileExtName){// gif文件,大小校验,超过4兆,不上传if("gif".equals(fileExtName)){if(uploadFile.getFileSize() > 4 * 1024 * 1024){throw new CommonException("GIF动图大小不能超过4M");}} else if(VIDEO_TYPE.contains(fileExtName)){if(uploadFile.getFileSize() > 40 * 1024 * 1024){throw new CommonException("视频大小不能超过40M");}} else{// 普通图片文件不能超过10Mif(uploadFile.getFileSize() > 10 * 1024 * 1024){throw new CommonException("上传单张图片不能超过10M");}}}/*** 上传原文件* @param fastFileStorageClient* @param uploadFile* @param imageServer* @param fileStream* @param fileExtName*/private static void uploadOrigFile(FastFileStorageClient fastFileStorageClient, UploadFile uploadFile, String imageServer,byte[] fileStream, String fileExtName){try (ByteArrayInputStream is = new ByteArrayInputStream(fileStream)) {StorePath originalStorePath = fastFileStorageClient.uploadFile( is, uploadFile.getFileSize(), fileExtName, null);uploadFile.setFullFilename(imageServer.concat("/").concat( originalStorePath.getFullPath()));} catch (IOException e) {log.error("upload Image error", e.getCause());throw new FdfsUploadImageException("upload Image error", e.getCause());}}/*** 上传图片缩略图* @param fastFileStorageClient* @param uploadFile* @param imageServer* @param fileStream* @param fileExtName* @param needThumbnail* @param needSize* @throws IOException*/private static void uploadImageThumbnails( FastFileStorageClient fastFileStorageClient, UploadFile uploadFile, String imageServer, byte[] fileStream, String fileExtName, Byte needThumbnail, Byte needSize) throws IOException {// 默认图片缩略图取原图uploadFile.setThumbnail(uploadFile.getFullFilename());// 缩略图也需要计算图片尺寸大小if(Constant.YES.equals(needSize) || Constant.YES.equals(needThumbnail)){// 获取图片尺寸BufferedImage bufferedImage = ImageIO.read(new ByteArrayInputStream( fileStream));if(bufferedImage != null){uploadFile.setWidth(bufferedImage.getWidth());uploadFile.setHeight(bufferedImage.getHeight());// 压缩处理if(Constant.YES.equals(needThumbnail)){InputStream is = null;try {ByteArrayOutputStream out = new ByteArrayOutputStream();float outputQuality = getOutputQuality( uploadFile.getFileSize());if(!"jpg".equals(fileExtName)){// 先转成jpgString newPicPath = IMG_LINUX_LOCATION + File.separator + UUID.randomUUID().toString() + ".jpg";Thumbnails.of(new ByteArrayInputStream(fileStream)) .scale(1f).toFile(newPicPath);// 原比例不变,大小压缩Thumbnails.of(newPicPath).scale(1f) .outputQuality(outputQuality).toOutputStream(out);// 删除jpg图片new File(newPicPath).delete();} else {Thumbnails.of(new ByteArrayInputStream(fileStream)) .scale(1f).outputQuality(outputQuality) .toOutputStream(out);}is = new ByteArrayInputStream(out.toByteArray());// 上传缩略图StorePath thumbnailStorePath = fastFileStorageClient .uploadFile(is, is.available(), fileExtName, null);uploadFile.setThumbnail(imageServer.concat("/") .concat(thumbnailStorePath.getFullPath()));log.info("上传缩略图地址={}", uploadFile.getThumbnail());} catch (IOException e) {log.error("upload ThumbImage error", e.getCause());throw new FdfsUploadImageException( "upload ThumbImage error",e.getCause());} finally {IOUtils.closeQuietly(is);}}}}}/*** 设置压缩比例* @param fileSize* @return*/private static float getOutputQuality(long fileSize){if (fileSize < 64 * 1024) {return 1f;} else if (fileSize < 256 * 1024) {return 0.4f;} else if (fileSize < 2 * 1024 * 1024) {return 0.2f;}return 0.1f;}/*** 判断文件格式是否支持* @param fileExtName* @return*/private static boolean isSupportType(String fileExtName) {return IMAGE_TYPE.contains(fileExtName) || VIDEO_TYPE.contains(fileExtName);}/*** 删除文件* @param fileUrl 文件访问地址* @param fastFileStorageClient*/public static void deleteFile(FastFileStorageClient fastFileStorageClient, String fileUrl) {if (StringUtils.isEmpty(fileUrl)) {return;}try {StorePath storePath = StorePath.parseFromUrl(fileUrl);fastFileStorageClient.deleteFile( storePath.getGroup(), storePath.getPath());} catch (FdfsUnsupportStorePathException e) {log.warn("异常信息:", e);}}}
3.2 前端上传文件API
import com.github.tobato.fastdfs.service.FastFileStorageClient;import io.swagger.annotations.Api;import io.swagger.annotations.ApiOperation;import lombok.extern.slf4j.Slf4j;import org.apache.commons.io.FilenameUtils;import org.springframework.beans.factory.annotation.Autowired;import org.springframework.beans.factory.annotation.Value;import org.springframework.http.MediaType;import org.springframework.http.ResponseEntity;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 java.util.ArrayList;import java.util.List;@Slf4j@RestController@RequestMapping("/fdfs")@Api(tags = "文件上传")public class FdfsController {@Value("${fdfs.web-server-url}")private String imageServer;@Autowiredprivate FastFileStorageClient fastFileStorageClient;@PostMapping(value = "/upload", consumes = MediaType.MULTIPART_FORM_DATA_VALUE, produces = MediaType.APPLICATION_JSON_VALUE)@ApiOperation(value = "文件上传", httpMethod = "POST")public String upload(@RequestParam("file") MultipartFile file,@RequestParam(value = "needSize", defaultValue = "0") Byte needSize,@RequestParam(value = "needThumbnail", defaultValue = "0") Byte needThumbnail) {try {long start = System.currentTimeMillis();// 获取文件后缀String fileExtName = FilenameUtils.getExtension( file.getOriginalFilename()).toUpperCase();UploadFile uploadFile = FdfsUtil.upload( fastFileStorageClient, file, imageServer, needThumbnail, needSize);long end = System.currentTimeMillis();log.info("文件上传耗时:{} 耗秒", (end - start));return JSON.toJSONString(uploadFile);} catch (Exception e) {log.error("上传文件异常:", e);}log.warn(String.format("文件 %s 上传失败", file.getOriginalFilename()));return "上传文件异常";}}
3.3 服务端上传文件
@Value("${fdfs.web-server-url}")private String imageServer;@Autowiredprivate FastFileStorageClient fastFileStorageClient;
File file = new File("xxxx");UploadFile uploadFile = FdfsUtil.upload( fastFileStorageClient, file, imageServer, null, null);String fileUrl = uploadFile.getFullFilename();file.deleteOnExit();return fileUrl;
4.FastDFS工作过程



client 连接请求FastDFS,需借助Nginx做http请求代理转发。
边栏推荐
- Exclusive lock
- shell编程
- 针对前面文章的整改思路
- Differences and relations between varchar and nvarchar in database
- Children's programming electronic society graphical programming level examination scratch level 1 real problem analysis (multiple choice) June 2022
- Fastdfs supports dual IP and IPv6
- FastDFS-支持双IP、IPV6
- C#使用log4net插件,输出日志到文件
- 【硬十宝典】——7.2【动态RAM】DDR4与DDR3区别解析
- Rust language - slice type (&[u8])
猜你喜欢

28. Implement strStr()实现 strStr()

『HarmonyOS』DevEco的下载安装与开发环境搭建

MySQL Foundation (II) -- MySQL Foundation

【无标题】转载

Use and analysis of show profile optimized by MySQL

从Architecture带你认识JVM

Binary tree knowledge summary

"Harmonyos" explore harmonyos applications

buuReserve(4)

Summarize and learn STM32 to create project template
随机推荐
Shell programming
[hardware ten treasures] - 7.1 [dynamic RAM] key points of DDR hardware design
Fastdfs supports dual IP and IPv6
Merge_sort
MySQL execution plan
服装行业如何实现数字化生产模式
Go language configuration vscade
Summary of common usage of dev treelist
Downloadutilse tool class without error
在第一次使用德国小鸡要注意的地方
曲线曲率展示
Vim中删除^M
Curve curvature display
7. Reverse integer integer
one hundred and twenty-three million one hundred and twenty-three thousand one hundred and twenty-three
替换license是否要重启数据库?
7. Reverse Integer整数反转
MySQL optimized index and index invalidation
Can you learn fast and well with dual stream network? Harbin Institute of Technology & Microsoft proposed a distillation dual encoder model for visual language understanding, which can achieve fast an
Log rotation logrotate
