一、传统使用
1.将fastdfs_client.jar导入工程
2.加载配置文件(如conf.properties),配置文件中的内容就是tracker服务的地址。
配置文件内容:tracker_server=192.168.25.133:22122
3.把commons-io、fileupload 的jar包添加到工程中
4.页面代码
页面使用的是KindEditor的多图片上传插件
KindEditor 4.x 文档:http://kindeditor.net/doc.php
参数:MultiPartFile uploadFile
返回值:
5、spring文件配置多媒体解析器
<!-- 定义文件上传解析器 --> <bean id="multipartResolver" class="org.springframework.web.multipart.commons.CommonsMultipartResolver"> <!-- 设定默认编码 --> <property name="defaultEncoding" value="UTF-8"></property> <!-- 设定文件上传的最大值5MB,5*1024*1024 --> <property name="maxUploadSize" value="5242880"></property> </bean>
6、上传代码(kindeditor对text/plain返回类型支持最好,如果返回json不兼容改为返回string)
@Controller public class PictureController { @Value("${IMAGE_SERVER_URL}") private String IMAGE_SERVER_URL; @RequestMapping("/pic/upload") @ResponseBody public Map fileUpload(MultipartFile uploadFile) { try { //1、取文件的扩展名 String originalFilename = uploadFile.getOriginalFilename(); String extName = originalFilename.substring(originalFilename.lastIndexOf(".") + 1); //2、创建一个FastDFS的客户端 FastDFSClient fastDFSClient = new FastDFSClient("classpath:resource/client.conf"); //3、执行上传处理 String path = fastDFSClient.uploadFile(uploadFile.getBytes(), extName); //4、拼接返回的url和ip地址,拼装成完整的url String url = IMAGE_SERVER_URL + path; //5、返回map Map result = new HashMap<>(); result.put("error", 0); result.put("url", url); return result; } catch (Exception e) { e.printStackTrace(); //5、返回map Map result = new HashMap<>(); result.put("error", 1); result.put("message", "图片上传失败"); return result; } } }
二、SpringBoot使用FastDFS
1.新建viuman-upload微服务。pom.xml:
<?xml version="1.0" encoding="UTF-8"?> <project xmlns="http://maven.apache.org/POM/4.0.0" xmlns:xsi="http://www.w3.org/2001/XMLSchema-instance" xsi:schemaLocation="http://maven.apache.org/POM/4.0.0 http://maven.apache.org/xsd/maven-4.0.0.xsd"> <parent> <artifactId>viuman</artifactId> <groupId>com.viuman</groupId> <version>1.0-SNAPSHOT</version> </parent> <modelVersion>4.0.0</modelVersion> <artifactId>viuman-upload</artifactId> <dependencies> <dependency> <groupId>com.viuman</groupId> <artifactId>viuman-common</artifactId> <version>1.0-SNAPSHOT</version> </dependency> <dependency> <groupId>org.springframework.cloud</groupId> <artifactId>spring-cloud-starter-netflix-eureka-client</artifactId> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-web</artifactId> </dependency> <dependency> <groupId>com.github.tobato</groupId> <artifactId>fastdfs-client</artifactId> <version>1.26.2</version> </dependency> <dependency> <groupId>org.springframework.boot</groupId> <artifactId>spring-boot-starter-test</artifactId> </dependency> </dependencies> </project>
2.application.yml
server:
port: 8082
spring:
application:
name: upload
servlet:
multipart:
max-file-size: 5MB # 限制文件上传的大小
# Eureka
eureka:
client:
service-url:
defaultZone: http://127.0.0.1:10086/eureka
instance:
lease-renewal-interval-in-seconds: 5 # 每隔5秒发送一次心跳
lease-expiration-duration-in-seconds: 10 # 10秒不发送就过期
prefer-ip-address: true
ip-address: 127.0.0.1
instance-id: ${spring.application.name}:${server.port}
# FastDFS
fdfs:
so-timeout: 1501
connect-timeout: 601
thumb-image: # 缩略图
60
height: 60
tracker-list: # tracker地址
- tracker.viuman.com:22122
IMAGE_SERVER_DOMAIN: http://image.viuman.com/
3.启动类
package com.viuman; import org.springframework.boot.SpringApplication; import org.springframework.boot.autoconfigure.SpringBootApplication; import org.springframework.cloud.client.discovery.EnableDiscoveryClient; @SpringBootApplication @EnableDiscoveryClient public class UploadApplication { public static void main(String[] args) { SpringApplication.run(UploadApplication.class); } }
4.修改网关微服务的application.yml。忽略路由上传微服务
zuul:
prefix: /api # 添加路由前缀
retryable: true
routes:
item-service: /item/** #将商品微服务映射到/item/**
ignored-services: upload #忽略路由该服务
5.创建Cors跨域配置类。详见https://www.cnblogs.com/naixin007/p/10420684.html
6.引入fdfs配置类
package com.viuman.config; 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; @Configuration @Import(FdfsClientConfig.class) //解决jmx重复注册bean的问题 @EnableMBeanExport(registration = RegistrationPolicy.IGNORE_EXISTING) public class FastClientImporter { }
7.service层上传代码
package com.viuman.upload.service.impl; import com.github.tobato.fastdfs.domain.StorePath; import com.github.tobato.fastdfs.domain.ThumbImageConfig; import com.github.tobato.fastdfs.service.FastFileStorageClient; import com.viuman.entity.Status; import com.viuman.exception.BusinessException; import com.viuman.upload.service.UploadService; import org.apache.commons.lang3.StringUtils; import org.springframework.beans.factory.annotation.Autowired; import org.springframework.beans.factory.annotation.Value; import org.springframework.stereotype.Service; import org.springframework.web.multipart.MultipartFile; import javax.imageio.ImageIO; import java.awt.image.BufferedImage; import java.io.IOException; import java.util.Arrays; import java.util.List; @Service public class UploadServiceImpl implements UploadService { @Autowired private FastFileStorageClient storageClient; @Autowired private ThumbImageConfig thumbImageConfig; @Value("${IMAGE_SERVER_DOMAIN}") private String IMAGE_SERVER_DOMAIN; //支持的文件类型 List<String> suffixes = Arrays.asList("image/png", "image/jpeg"); @Override public String upload(MultipartFile file) { if (null == file) { throw new BusinessException(Status.PARAM_LACK_ERROR); } if (!suffixes.contains(file.getContentType())) { throw new BusinessException(Status.PARAM_ILLEGAL_ERROR.setMsg("文件类型不支持")); } try { BufferedImage image = ImageIO.read(file.getInputStream()); if (null == image) { throw new BusinessException(Status.PARAM_ILLEGAL_ERROR.setMsg("文件内容不符合要求")); } } catch (IOException e) { e.printStackTrace(); } StorePath storePath = null; String extension = StringUtils.substringAfterLast(file.getOriginalFilename(), "."); try { storePath = storageClient.uploadImageAndCrtThumbImage(file.getInputStream(), file.getSize(), extension, null); } catch (IOException e) { e.printStackTrace(); } if (null == storePath || StringUtils.isBlank(storePath.getFullPath())) { throw new BusinessException(Status.REMOTE_ERROR.setMsg("上传失败")); } String url = IMAGE_SERVER_DOMAIN + storePath.getFullPath(); return url; } }
8.上传返回结果
原图路径:http://image.viuman.com/group1/M00/00/00/rBHRQl2UbEWAWsRwAAFWAkILswQ447.png
缩略图路径:http://image.viuman.com/group1/M00/00/00/rBHRQl2UbEWAWsRwAAFWAkILswQ447_60x60.png
9.删除文件
/** * 删除文件 * @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) { logger.warn(e.getMessage()); } }