
正文
通过Fastdfs进行文件上传服务(文件和图片的统一处理)
提示:扫一扫查出行【扫一扫了解最新限行尾号】
复制提示
1、文件上传简单流程分析图:

2、Fastdfs介绍:
Fastdfs由两个角色组成:
Tracker(集群):调度(帮你找到有空闲的Storage)
Storage(集群):文件存储(帮你保存文件或获取需要的文件)
流程:
1.Storage和tracker 发送心跳连接。
2.客户端请求tracker,tracker调度一个Storage,返回Storage的ip和端口。
3.客户端请求Storage,上传文件。
4.Storage保存文件,生成file_id,并返回。
5.客户端接收到file_id并保存。
3、上传下载流程图:
上传:

下载:

4、Fastdfs上传具体实现步骤:
1. 在服务器上搭建好fastdfs环境:这个由运维人员操作,开发人员无需关心。
2. 在本地maven仓库导入fastdfs的jar包(该jar包在maven中央仓库中没有,无法通过idea自动下载,只能手动导入到本地仓库中去)
jar包下载地址(fastdfs_client_v1.20.jar):https://sourceforge.net/projects/fastdfs/files/Java%20Client%20API%20Library/Java%20Client%20Library%20V1.20%20%28compiled%20by%20JDK%201.6%29/fastdfs_client_v1.20.jar/download?use_mirror=liquidtelecom&download=&failedmirror=jaist.dl.sourceforge.net
导入本地仓库:
在jar包所在的目录打开cmd,然后输入以下命令,执行后即可在maven本地仓库导入jar包并在cmd显示出jar包在仓库中的路径。
mvn install:install-file -DgroupId=org.csource.fastdfs -DartifactId=fastdfs -Dversion=1.2 -Dpackaging=jar -Dfile= fastdfs_client_v1.20.jar |
3. 项目中引入
<dependency>
<groupId>org.csource.fastdfs</groupId>
<artifactId>fastdfs</artifactId>
<version>1.2</version>
</dependency>
4、项目中引入以下工具类:
fdfs_client.conf 文件(用于保存指向 tracker 的IP+端口(默认)):
tracker_server=172.16.2.274:
工具类:
import org.csource.common.NameValuePair;
import org.csource.fastdfs.ClientGlobal;
import org.csource.fastdfs.StorageClient;
import org.csource.fastdfs.StorageServer;
import org.csource.fastdfs.TrackerClient;
import org.csource.fastdfs.TrackerServer;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 {
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 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;
}
}// @Test
// public void testGetFileInfo(){
// try {
// ClientGlobal.init(conf_filename);
//
// TrackerClient tracker = new TrackerClient();
// TrackerServer trackerServer = tracker.getConnection();
// StorageServer storageServer = null;
//
// StorageClient storageClient = new StorageClient(trackerServer, storageServer);
// FileInfo fi = storageClient.get_file_info("group1", "M00/00/00/wKgRcFV_08OAK_KCAAAA5fm_sy874.conf");
// System.out.println(fi.getSourceIpAddr());
// System.out.println(fi.getFileSize());
// System.out.println(fi.getCreateTimestamp());
// System.out.println(fi.getCrc32());
// } catch (Exception e) {
// e.printStackTrace();
// }
// }// @Test
// public void testGetFileMate(){
// try {
// ClientGlobal.init(conf_filename);
//
// TrackerClient tracker = new TrackerClient();
// TrackerServer trackerServer = tracker.getConnection();
// StorageServer storageServer = null;
//
// StorageClient storageClient = new StorageClient(trackerServer,
// storageServer);
// NameValuePair nvps [] = storageClient.get_metadata("group1", "M00/00/00/wKgRcFV_08OAK_KCAAAA5fm_sy874.conf");
// for(NameValuePair nvp : nvps){
// System.out.println(nvp.getName() + ":" + nvp.getValue());
// }
// } catch (Exception e) {
// e.printStackTrace();
// }
// } /**
* 删除文件
* @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());
}
}
}
5、在contorller中使用:
@RestController
public class FileController { /**
* 文件上传 MultipartFile 是SpringMVC封装好的API方便操作上传的文件的
* @param file
* @return
*/
@PostMapping("/fastdfs")
public AjaxResult upload(MultipartFile file){ try {
//获取文件的扩展名
String filename = file.getOriginalFilename();
String extName = filename.substring(filename.lastIndexOf(".")+1);
String file_id = FastDfsApiOpr.upload(file.getBytes(), extName);
return AjaxResult.me().setSuccess(true).setMessage("上传成功!").setRestObj(file_id);
} catch (Exception e) {
e.printStackTrace();
return AjaxResult.me().setSuccess(false).setMessage("上传失败!"+e.getMessage());
} } /**
* 删除文件
* @param file_id
* @return
*/
@DeleteMapping("/fastdfs")
public AjaxResult delete(String file_id){
try {
// /group1/M00/00/01/rBACgF1euQiAEdrcAACbjnUEnrE193.jpg file_id = file_id.substring(1);// group1/M00/00/01/rBACgF1euQiAEdrcAACbjnUEnrE193.jpg String groupName = file_id.substring(0, file_id.indexOf("/")); String fileName = file_id.substring(file_id.indexOf("/")+1); FastDfsApiOpr.delete(groupName, fileName); return AjaxResult.me().setSuccess(true).setMessage("删除成功!"); } catch (Exception e) {
e.printStackTrace(); return AjaxResult.me().setSuccess(false).setMessage("删除失败!"); } }}
5.1控制文件上传的大小
为了解决有些文件因大于默认上传文件大小的而无法上传的问题,可以在网关模块和引用Fastdfs的controller所在的模块的启动类上加上如下代码:
/**
* 文件大小上传配置
* @return
*/
@Bean
public MultipartConfigElement multipartConfigElement() {
MultipartConfigFactory factory = new MultipartConfigFactory();
//单个文件最大
factory.setMaxFileSize("10240KB"); //KB,MB
/// 设置总上传数据总大小
factory.setMaxRequestSize("102400KB");
return factory.createMultipartConfig();
}
6、前端页面代码
<el-form-item label="logo">
<el-upload
class="upload-demo"
action="http://localhost:6001/services/common/fastdfs"
:file-list="addForm.logoList"
list-type="picture"
:on-success="logoUploadSuccess"
:before-upload="handleBeforeUpload"
:on-remove="handleLogoRemove">
<el-button size="small" type="primary">点击上传</el-button>
</el-upload>
</el-form-item>
methods: {
handleLogoRemove(file, fileList){
//file 删除的文件
//调用删除文件的接口
let file_id = file.response.restObj
this.$http.delete("/common/fastdfs?file_id="+file_id)
.then(res=>{
let {success,message,restObj} = res.data;
if(success){
//fileList 删除后的文件列表
this.addForm.logoList = fileList;
}else{
this.$message({
message:message,
type:"error"
})
}
})
},
//图片上传之前的回调
handleBeforeUpload(file){
if(this.addForm.logoList.length>0){
this.$message({
message:"只能上传一张图片!",
type:"warning"
})
return false;
}
},
//图片上传成功的回调
logoUploadSuccess(response, file, fileList){
//fileList = [{response:{success:true,restObj:''}},file,file]
this.addForm.logoList = fileList;
console.log(response)
}
}








