选择合适分布式集群文件系统:安全,可以备份,统一处理的,避免了文件放置某一个服务器,不能集群的问题.
阿里云、七牛云…
就是上面的原因图示
用C语言编写的,开源的分布式文件系统,它考虑了冗余备份、负载均衡、线性扩容等机制,为互联网量身定制。注重高可用,高性能等指标。使用fastdfs很容易搭建一套高性能的文件服务集群,提供上传、下载等服务。
管理集群 。客户端请求 Tracker server 进行文件上传、下载,通过 Tracker server 调度最终由 Storage server 完成文件上传和下载。
Tracker server 作用是负载均衡和调度,通过 Tracker server 在文件上传时可以根据一些策略找到 Storage server 提供文件上传服务。可以将 tracker 称为追踪服务器或调度服务器。
实际保存文件。Storage server 作用是文件存储,客户端上传的文件最终存储在 Storage 服务器上,Storageserver 没有实现自己的文件系统而是利用操作系统 的文件系统来管理文件。可以将storage称为存储服务器。
maven不能自动到中央仓库下载Fastdfs依赖包。要在Github上下载压缩包,并配置在maven仓库中,然后引入pom.xml文件才能使用
下载fastdfs的压缩包
在增加个文件操作的工具依赖
org.csource
fastdfs-client-java
1.27-SNAPSHOT
commons-io
commons-io
2.6
@FeignClient(value="COMMON-PROVIDER",fallback = FastDfsFall.class)
public interface FastDfsClient {
//上传和下载和删除:
@RequestMapping(value = "/common/upload",method = RequestMethod.POST)
AjaxResult upload(@RequestBody MultipartFile file);
//下载:页面直接使用http://ip/groupname/filename
//删除:
@RequestMapping(value = "/common/delete",method = RequestMethod.GET)
AjaxResult delete(@RequestParam("filePath") String filePath);
}
@Component
public class FastDfsFall implements FastDfsClient{
@Override
public AjaxResult upload(MultipartFile file) {
return AjaxResult.me().setSuccess(false).setMsg("亲,现在我们的服务很忙,亲稍后在试哦!!!!");
}
@Override
public AjaxResult delete(String filePath) {
return AjaxResult.me().setSuccess(false).setMsg("亲,现在我们的服务很忙,亲稍后在试哦!!!!");
}
}
@RestController
@RequestMapping("/common")
public class FastDfsController implements FastDfsClient {
@RequestMapping(value = "/upload",method = RequestMethod.POST)
@Override
public AjaxResult upload(@RequestBody MultipartFile file) {
try {
byte[] bytes = file.getBytes();
//获取原始名:
String originalFilename = file.getOriginalFilename();
//获取后缀名:
String extName = FilenameUtils.getExtension(originalFilename);
// "/"+fileIds[0]+"/"+fileIds[1];
String groupNameAndFileName = FastDfsApiOpr.upload(bytes, extName);
return AjaxResult.me().setSuccess(true).setMsg("亲,文件上传成功!").setObject(groupNameAndFileName);
} catch (IOException e) {
e.printStackTrace();
return AjaxResult.me().setSuccess(false).setMsg("亲,文件上传失败!"+e.getMessage());
}
}
@RequestMapping(value = "/delete",method = RequestMethod.GET)
@Override
public AjaxResult delete(@RequestParam("filePath") String filePath) {
// filePath: http://ip/groupName/fileName
// /groupName/fileName groupName/fileName
String filePath1 =filePath.substring(1);
String groupName= filePath1.substring(0, filePath1.indexOf("/"));
String fileName=filePath1.substring(filePath1.indexOf("/")+1);
int delete = FastDfsApiOpr.delete(groupName, fileName);
if(delete==0){
return AjaxResult.me().setSuccess(true).setMsg("删除成功!!");
}else{
return AjaxResult.me().setSuccess(false).setMsg("删除失败!!");
}
}
//拿到的图片存储位置是:组名+路径 用string类型的方法将两者分开来
public static void main(String[] args) {
String filePath="/group1/M00/00/01/rBAHy1zYO26AEwFyAAB7VaQUqSY146.png";
// group1
// M00/00/01/rBAHy1zYLluAMw2BAC7Mdh1oFjs624.avi
String groupName="";
// filePath.indexOf("0"):第一个字符串出现的索引:从0开始
// groupName.substring(0, 2):ab [)==>左闭右开
// group1/M00/00/01/rBAHy1zYO26AEwFyAAB7VaQUqSY146.png:只有一个参数的时候:从这个开始截取到最后:filePath.substring(1)
String filePath1 =filePath.substring(1);// group1/M00/00/01/rBAHy1zYO26AEwFyAAB7VaQUqSY146.png
// group1
groupName= filePath1.substring(0, filePath1.indexOf("/"));
String fileName=filePath1.substring(filePath1.indexOf("/")+1);
}
}
public class FastDfsApiOpr {
public static String CONF_FILENAME = FastDfsApiOpr.class.getResource("/fdfs_client.conf").getFile();
/**
* 上传文件
* @param file
* @param extName
* @return
*/
public static String upload(byte[] file,String extName) {
try {
// 1、加载配置文件,配置文件中的内容就是 tracker 服务的地址。
ClientGlobal.init(CONF_FILENAME);
// 2、创建一个 TrackerClient 对象。直接 new 一个。
TrackerClient tracker = new TrackerClient();
// 3、使用 TrackerClient 对象创建连接,获得一个 TrackerServer 对象。
TrackerServer trackerServer = tracker.getConnection();
// 4、创建一个 StorageServer 的引用,值为 null
StorageServer storageServer = null;
// 5、创建一个 StorageClient 对象,需要两个参数 TrackerServer 对象、StorageServer 的引用
StorageClient storageClient = new StorageClient(trackerServer, storageServer);
NameValuePair nvp [] = new NameValuePair[]{
new NameValuePair("age", "18"),
new NameValuePair("sex", "male")
};
// 6、使用 StorageClient 对象上传图片。返回数组。包含组名和图片的路径。
String fileIds[] = storageClient.upload_file(file,extName,nvp);
System.out.println(fileIds.length);
System.out.println("组名:" + fileIds[0]);
System.out.println("路径: " + fileIds[1]);
return "/"+fileIds[0]+"/"+fileIds[1];
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 下载文件
* @param groupName
* @param fileName
* @return
*/
public static byte[] download(String groupName,String fileName) {
try {
ClientGlobal.init(CONF_FILENAME);
TrackerClient tracker = new TrackerClient();
TrackerServer trackerServer = tracker.getConnection();
StorageServer storageServer = null;
StorageClient storageClient = new StorageClient(trackerServer, storageServer);
byte[] b = storageClient.download_file(groupName, fileName);
return b;
} catch (Exception e) {
e.printStackTrace();
return null;
}
}
/**
* 删除文件
* @param groupName
* @param fileName
*/
public static int delete(String groupName,String fileName){
try {
ClientGlobal.init(CONF_FILENAME);
TrackerClient tracker = new TrackerClient();
TrackerServer trackerServer = tracker.getConnection();
StorageServer storageServer = null;
StorageClient storageClient = new StorageClient(trackerServer,
storageServer);
int i = storageClient.delete_file(groupName,fileName);
System.out.println( i==0 ? "删除成功" : "删除失败:"+i);
return i;
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("删除异常,"+e.getMessage());
}
}
}
io.springfox
springfox-swagger2
2.9.2
io.springfox
springfox-swagger-ui
2.9.2
注意:swagger要扫描controller层的包
@Configuration
@EnableSwagger2
public class Swagger2 {
@Bean
public Docket createRestApi() {
return new Docket(DocumentationType.SWAGGER_2)
.apiInfo(apiInfo())
.select()
.apis(RequestHandlerSelectors.basePackage("cn.itsource.aigou.controller"))
//包:就是自己接口的包路径
.paths(PathSelectors.any())
.build();
}
private ApiInfo apiInfo() {
return new ApiInfoBuilder()
.title("商品系统api")//名字
.description("商品系统接口文档说明")//额外藐视
.contact(new Contact("wbtest", "", "[email protected]"))
.version("1.0")// 版本
.build();
}
}
是公共服务模块aigou_common_service中的YAMLname配置