一、传统使用
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: # 缩略图
width: 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