使用 Springboot 在docker 上搭建FastDFS文件服务器, 并上传文件到FastDFS服务器中
本文只记录使用Springboot完成文件上传的过程,安装docker和搭建FastDFS文件服务器请参考链接:** docker+fastdfs+springboot一键式搭建分布式文件服务器.
1. 前端文件上传页面(html)
<!DOCTYPE html>
<html xmlns:th="http://www.thymeleaf.org">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=no">
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<meta http-equiv="X-UA-Compatible" content="IE=Edge">
<title>资料上传</title>
<link rel="shortcut icon" th:href="@{/favicon.ico}"/>
<link rel="stylesheet" type="text/css" th:href="@{/static/bootstrap/css/bootstrap.min.css}" />
<link rel="stylesheet" type="text/css" th:href="@{/static/css/base.css}" />
<link rel="stylesheet" type="text/css" th:href="@{/static/css/page.css}"/>
<!--[if lt IE 9]>
<script src="https://oss.maxcdn.com/libs/html5shiv/3.7.0/html5shiv.js"></script>
<script src="https://oss.maxcdn.com/libs/respond.js/1.3.0/respond.min.js"></script>
<![endif]-->
<script th:src="@{/static/js/jquery-3.3.1.min.js}"></script>
<script th:src="@{/static/bootstrap/js/bootstrap.min.js}"></script>
</head>
<body>
<!--欢迎页面-->
<div class="welcomewrap">
<div class="container">
<div class="row">
<div class="col-lg-12 col-md-12 text-center">
<!--右侧下面部分-->
<!--页头-->
<div class="page-header">
<h1>资料 <small>上传</small></h1>
</div>
<!--发布项目到index.html列表-->
<div class="sendObject center-block text-center">
<form id="loginform" class="form-horizontal" method="post" enctype="multipart/form-data" th:action="@{sourceUpload}">
<div class="form-group">
<label class="col-sm-2 control-label">文件</label>
<div class="col-sm-10">
<!--<input type="file" id="inputPassword3" placeholder="图片">-->
<input type="file" id="chooseImage" name="file">
</div>
</div>
<div class="form-group">
<div class="col-sm-offset-2 col-sm-10">
<button type="submit" class="btn btn-default updatabtn" alt="">上传</button>
</div>
</div>
</form>
</div>
</div>
</div>
</div>
</div>
</body>
</html>
注意:做文件上传功能时,请求方法一定要为 post,即:method=post 还要设置一个属性:enctype=“multipart/form-data”
2. POJO类
package com.wulaobo.bean;
import java.io.Serializable;
public class Source implements Serializable {
private Integer id;
private String filename;
private String filepath;
public String getFilepath() {
return filepath;
}
public void setFilepath(String filepath) {
this.filepath = filepath;
}
private String pubtime;
public Integer getId() {
return id;
}
public void setId(Integer id) {
this.id = id;
}
public String getFilename() {
return filename;
}
public void setFilename(String filename) {
this.filename = filename;
}
public String getPubtime() {
return pubtime;
}
public void setPubtime(String pubtime) {
this.pubtime = pubtime;
}
@Override
public String toString() {
return "Source{" +
"id=" + id +
", filename='" + filename + '\'' +
", filepath='" + filepath + '\'' +
", pubtime='" + pubtime + '\'' +
'}';
}
}
3. FastDFSClient工具类
package com.wulaobo.utils;
import com.github.tobato.fastdfs.conn.FdfsWebServer;
import com.github.tobato.fastdfs.domain.StorePath;
import com.github.tobato.fastdfs.proto.storage.DownloadByteArray;
import com.github.tobato.fastdfs.service.FastFileStorageClient;
import org.apache.commons.io.FilenameUtils;
import org.apache.commons.lang3.StringUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Component;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
@Component
public class FastDFSClient {
private static Logger log = LoggerFactory.getLogger(FastDFSClient.class);
private static FastFileStorageClient fastFileStorageClient;
private static FdfsWebServer fdfsWebServer;
@Autowired
public void setFastDFSClient(FastFileStorageClient fastFileStorageClient, FdfsWebServer fdfsWebServer) {
FastDFSClient.fastFileStorageClient = fastFileStorageClient;
FastDFSClient.fdfsWebServer = fdfsWebServer;
}
/**
* @param multipartFile 文件对象
* @return 返回文件地址
* @author qbanxiaoli
* @description 上传文件
*/
public static String uploadFile(MultipartFile multipartFile) {
try {
StorePath storePath = fastFileStorageClient.uploadFile(multipartFile.getInputStream(),
multipartFile.getSize(), FilenameUtils.getExtension(multipartFile.getOriginalFilename()), null);
return storePath.getFullPath();
} catch (IOException e) {
log.error(e.getMessage());
return null;
}
}
/**
* @param multipartFile 图片对象
* @return 返回图片地址
* @author qbanxiaoli
* @description 上传缩略图
*/
public static String uploadImageAndCrtThumbImage(MultipartFile multipartFile) {
try {
StorePath storePath = fastFileStorageClient.uploadImageAndCrtThumbImage(multipartFile.getInputStream(),
multipartFile.getSize(), FilenameUtils.getExtension(multipartFile.getOriginalFilename()), null);
return storePath.getFullPath();
} catch (Exception e) {
log.error(e.getMessage());
return null;
}
}
/**
* @param file 文件对象
* @return 返回文件地址
* @author qbanxiaoli
* @description 上传文件
*/
public static String uploadFile(File file) {
try {
FileInputStream inputStream = new FileInputStream(file);
StorePath storePath = fastFileStorageClient.uploadFile(inputStream, file.length(),
FilenameUtils.getExtension(file.getName()), null);
return storePath.getFullPath();
} catch (Exception e) {
log.error(e.getMessage());
return null;
}
}
/**
* @param file 图片对象
* @return 返回图片地址
* @author qbanxiaoli
* @description 上传缩略图
*/
public static String uploadImageAndCrtThumbImage(File file) {
try {
FileInputStream inputStream = new FileInputStream(file);
StorePath storePath = fastFileStorageClient.uploadImageAndCrtThumbImage(inputStream, file.length(),
FilenameUtils.getExtension(file.getName()), null);
return storePath.getFullPath();
} catch (Exception e) {
log.error(e.getMessage());
return null;
}
}
/**
* @param bytes byte数组
* @param fileExtension 文件扩展名
* @return 返回文件地址
* @author qbanxiaoli
* @description 将byte数组生成一个文件上传
*/
public static String uploadFile(byte[] bytes, String fileExtension) {
ByteArrayInputStream stream = new ByteArrayInputStream(bytes);
StorePath storePath = fastFileStorageClient.uploadFile(stream, bytes.length, fileExtension, null);
return storePath.getFullPath();
}
/**
* @param fileUrl 文件访问地址
* @param file 文件保存路径
* @author qbanxiaoli
* @description 下载文件
*/
public static boolean downloadFile(String fileUrl, File file) {
try {
StorePath storePath = StorePath.praseFromUrl(fileUrl);
byte[] bytes = fastFileStorageClient.downloadFile(storePath.getGroup(), storePath.getPath(), new DownloadByteArray());
FileOutputStream stream = new FileOutputStream(file);
stream.write(bytes);
stream.close();
} catch (Exception e) {
log.error(e.getMessage());
return false;
}
return true;
}
/**
* @param fileUrl 文件访问地址
* @author qbanxiaoli
* @description 删除文件
*/
public static boolean deleteFile(String fileUrl) {
if (StringUtils.isEmpty(fileUrl)) {
return false;
}
try {
StorePath storePath = StorePath.praseFromUrl(fileUrl);
fastFileStorageClient.deleteFile(storePath.getGroup(), storePath.getPath());
} catch (Exception e) {
log.error(e.getMessage());
return false;
}
return true;
}
// 封装文件完整URL地址
public static String getResAccessUrl(String path) {
String url = fdfsWebServer.getWebServerUrl() + path;
log.info("上传文件地址为:\n" + url);
return url;
}
}
4. 后台Controller层
package com.wulaobo.controller;
import com.github.pagehelper.PageHelper;
import com.github.pagehelper.PageInfo;
import com.wulaobo.bean.Source;
import com.wulaobo.service.SourceService;
import com.wulaobo.utils.DateUtil;
import com.wulaobo.utils.FastDFSClient;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.ui.ModelMap;
import org.springframework.web.bind.annotation.GetMapping;
import org.springframework.web.bind.annotation.PostMapping;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.multipart.MultipartFile;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
import java.net.URLEncoder;
import java.util.List;
@Controller
public class SourceController {
@Autowired
private SourceService sourceService;
@PostMapping(value = "/sourceUpload")
public String sourceUpload(MultipartFile file, HttpServletRequest request) {
Source source = new Source();
// String path = request.getServletContext().getRealPath("source");
// String path = "D:/upload/source/";
// source.setPubtime(DateUtil.getNowTime());
String filename = file.getOriginalFilename();
source.setFilename(filename);
//上传文件的关键两行代码
String str = FastDFSClient.uploadFile(file);
String filepath = FastDFSClient.getResAccessUrl(str);
source.setPubtime(DateUtil.getNowTime());
source.setFilepath(filepath);
boolean result = sourceService.addSource(source);
if (result) {
try {
// file.transferTo(fileDir);
return "admin/uploadSuccess";
} catch (Exception e) {
e.printStackTrace();
}
}
return "failed";
}
}
5. Service 接口层
package com.wulaobo.service;
import com.wulaobo.bean.Source;
import java.util.List;
public interface SourceService {
boolean addSource(Source source);
}
6. Service 实现层
package com.wulaobo.service.impl;
import com.wulaobo.bean.Source;
import com.wulaobo.mapper.SourceMapper;
import com.wulaobo.service.SourceService;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import java.util.List;
@Service
public class SourceServiceImpl implements SourceService {
@Autowired
private SourceMapper sourceMapper;
@Override
public boolean addSource(Source source) {
return sourceMapper.addSource(source);
}
}
7. Dao层
package com.wulaobo.mapper;
import com.wulaobo.bean.Source;
import java.util.List;
public interface SourceMapper {
boolean addSource(Source source);
}
8. Mapper映射文件
<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE mapper
PUBLIC "-//mybatis.org//DTD Mapper 3.0//EN"
"http://mybatis.org/dtd/mybatis-3-mapper.dtd">
<mapper namespace="com.wulaobo.mapper.SourceMapper">
<insert id="addSource" parameterType="source">
insert into t_source (filename,filepath,pubtime) values (#{filename},#{filepath},#{pubtime})
</insert>
</mapper>
项目完整代码已托管到github平台上: 点我看源码.
有问题请发邮件至:2480458124@qq.com 欢迎来交流哈