SpringBoot整合fastDfs图片文件上传

一、fastDFS是一个分布式文件系统,主要用于存储和管理大型二进制文件,例如图片、音频和视频等。

       1. Tracker服务器(Tracker Server):是FastDFS的服务端程序,用来协调存储和访问文件的操作,负责管理存储服务器(Storage Server)的地址信息以及判断存储服务器的可用性。

       2. Storage服务器(Storage Server):用于存储和管理文件的服务器,实际上是一个存储节点。

       3. Group(Group):指存储服务器的分组,文件上传后会分配到此组下的一个服务器上进行存储。

       4. FastDFS客户端(FastDFS Client):用来上传、下载和删除文件的应用程序组件,通常是通过FastDFS客户端API来实现的。

       5. Storage路径(Storage Path):由Group和文件名组成的全局唯一标识符,用于访问存储在FastDFS上的文件。

       6. Tracker路径(Tracker Path):由Group和Storage Server的IP和端口号组成的全局唯一标识符,用于访问Tracker服务器。

       7. Meta data:指用于描述文件属性的元数据,通常用于补充文件的说明、分类、统计、区分和检索等,FastDFS支持对自定义元数据进行存储,并支持查询和修改。

二、fastDfs的原理以及实现流程

       1.用户上传图片时,客户端会连接trackeServer,trackeServer去调用一个可用的StorageServer,返回StorageServer的ip和port。

       2.客户端会根据ip和prot去访问StorageServer,将资源传给StorageServer,然后会生成一个filed响应filed和文件路径。

       3.trackeServer和StorageServer要保持心跳机制,这样trackeServer才知道那个StorageServer是可用的。

三、SpringBoot整合fastDfs图片上传技术

1.引入FastDFS客户端依赖:在pom.xml中引入FastDFS客户端的相关依赖

<!--fastdfs-->
<dependency>
<groupId>cn.bestwu</groupId>
<artifactId>fastdfs-client-java</artifactId>
<version>1.27</version>
</dependency>

 2.使用fastDfs的工具类

package com.lzc.basic.utils;

import org.csource.common.NameValuePair;
import org.csource.fastdfs.*;
/**
* fastDfs工具类
*/
public class FastDfsUtils {

//从classpath:resources中的内容最终会编译到classpath下
public static String CONF_FILENAME = FastDfsUtils.class.getClassLoader()
.getResource("fdfs_client.conf").getFile();


/**
* 上传文件
* @param file
* @param extName
* @return
*/
public static String upload(byte[] file,String extName) {

try {
ClientGlobal.init(CONF_FILENAME);

TrackerClient tracker = new TrackerClient();
TrackerServer trackerServer = tracker.getConnection();
StorageServer storageServer = null;

StorageClient storageClient = new StorageClient(trackerServer, storageServer);
NameValuePair nvp [] = new NameValuePair[]{
new NameValuePair("age", "18"),
new NameValuePair("sex", "male")
};
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 extName
* @return
*/
public static String upload(String path,String extName) {

try {
ClientGlobal.init(CONF_FILENAME);
TrackerClient tracker = new TrackerClient();
TrackerServer trackerServer = tracker.getConnection();
StorageServer storageServer = null;
StorageClient storageClient = new StorageClient(trackerServer, storageServer);
String fileIds[] = storageClient.upload_file(path, extName,null);

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 void 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);
} catch (Exception e) {
e.printStackTrace();
throw new RuntimeException("删除异常,"+e.getMessage());
}
}
// public static void main(String[] args) {
// FastDfsUtils.delete("group1","M00/00/0F/oYYBAGJ6IGaAWQeOAAbMJw3URKE510.gif");
// }
}

 3.后端接口

package com.lzc.basic.controller;

import com.lzc.basic.exception.GlobalExceptionEnum;
import com.lzc.basic.utils.AjaxResult;
import com.lzc.basic.utils.FastDfsUtils;
import org.apache.commons.io.FilenameUtils;
import org.springframework.web.bind.annotation.*;
import org.springframework.web.multipart.MultipartFile;

import java.io.IOException;

/**
* 上传
* 下载 = 不需要
* 查看 = 路径
* 删除
* 更新 = 删除 + 上传
*/
@RestController
@RequestMapping("/fastDfs")
public class FastDfsController {
//@RequestPart对复杂表单项的处理,默认name="file",与上传文件的name属性值一致
@PostMapping
public AjaxResult upload(@RequestPart(required = true,value = "file") MultipartFile file){

try {
System.out.println(file.getOriginalFilename() + ":" + file.getSize());
// 1.从复杂对象中file.getBytes()获取到文件的byte数组 getOriginalFilename()获取原始名称
String originalFilename = file.getOriginalFilename();
// 2.FilenameUtils.getExtension(originalFilename);获取文件后缀名
String extName = FilenameUtils.getExtension(originalFilename);
// xxx.jpg
// String extName = originalFilename.substring(originalFilename.lastIndexOf(".")+1);
String filePath = FastDfsUtils.upload(file.getBytes(), extName);
return AjaxResult.success(filePath);//把上传后的路径返回回去
} catch (IOException e) {
e.printStackTrace();
return AjaxResult.error(GlobalExceptionEnum.UPLOAD_ERROR.getCode(),GlobalExceptionEnum.UPLOAD_ERROR.getMessage());
}
}
/**
* 参数:完整路径 /goup1/xxxxx/yyyy
* 返回值:成功与否,还要返回地址
* //模拟前端发送请求调用该接口1:Delete http://localhost:8080/fastDfs//group1/M00/04/72/CgAIC2QetIuAVFPIAAgFDuhQH8Q183.gif - 不用
//模拟前端发送请求调用该接口2:Delete http://localhost:8080/fastDfs?path=/group1/M00/04/72/CgAIC2QetIuAVFPIAAgFDuhQH8Q183.gif - 采用
*/
@DeleteMapping()
public AjaxResult del(@RequestParam(required = true,value = "path") String path){
String pathTmp = path.substring(1); // goup1/xxxxx/yyyy
String groupName = pathTmp.substring(0, pathTmp.indexOf("/")); //goup1
String remotePath = pathTmp.substring(pathTmp.indexOf("/")+1);// /xxxxx/yyyy
FastDfsUtils.delete(groupName, remotePath);
return AjaxResult.success(path);
}
}

四、前端vue和elementui

1.引入elementui组件

<el-form-item label="资源" prop="resources">
<!--<el-input v-model="editForm.resources" auto-complete="off"></el-input>-->
<el-upload
class="upload-demo"
action="http://localhost:8080/fastDfs"
:on-remove="handleRemove"
:on-success="handleSuccess"
:file-list="fileList"
list-type="picture">
<el-button size="small" type="primary">点击上传</el-button>
<div slot="tip" class="el-upload__tip">只能上传jpg/png文件,且不超过500kb</div>
</el-upload>
</el-form-item>

2. 图片上传和删除方法

handleSuccess(response, file, fileList) {
//1.只要把action属性写对了就可以上传了
//处理resources
if(this.editForm.resources){//有值
this.editForm.resources = this.editForm.resources+","+response.data;
}else{
this.editForm.resources = response.data;
}
//处理fileList:resources = xx,xx,xx
this.fileList=[];//先清空 - 再添加最新的所有该宠物图片
if(this.editForm.resources){
let arr = this.editForm.resources.split(",");//[xx,xx,xx]
for(var i = 0;i<arr.length;i++){
this.fileList.push({"url":"远端注册的地址"+arr[i]});
}
}
},

handleRemove(file, fileList) {
//1.调用删除接口删除fastdfs中的数据 :
var url = file.url;//
var path = url.substring(url.indexOf("/group"));// /group1/M00/00/0C/CgAIC2KrU4qAAy6HAAF5fdD2FCI828.jpg
this.$http.delete("/fastDfs?path="+path).then(res=>{
if(res.data.success){
this.$message.success("删除成功!!!");
}else{
this.$message.success("删除失败!!!");
}
})
//2.处理resources
if(this.editForm.resources){ // xx,yy,zz
let arr = this.editForm.resources.split(","); //[xx,yy,zz]
for(var i = 0;i<arr.length;i++){
if(path == arr[i]){//找到了删除的图片
arr.splice(i,1);
break;
}
} //[xx,zz]
this.editForm.resources = arr.join(","); //xx,zz
console.log(this.editForm.resources)
}
//3.处理fileList
this.fileList=[];//先清空 - 再添加最新的
if(this.editForm.resources){
let arr = this.editForm.resources.split(",");//[xx,xx,xx]
for(var i = 0;i<arr.length;i++){
this.fileList.push({"url":"远端注册的地址"+arr[i]});
}
}
},

猜你喜欢

转载自blog.csdn.net/lzc19991201/article/details/131196393