基于javaweb+mysql的springboot+jpa网盘系统设计和实现(javaweb+springboot+ssm+jpa+thymeleaf+html)
运行环境
Java≥8、MySQL≥5.7
开发工具
eclipse/idea/myeclipse/sts等均可配置运行
适用
课程设计,大作业,毕业设计,项目练习,学习演示等
功能说明
基于javaweb+mysql的SpringBoot+JPA网盘系统设计和实现(javaweb+springboot+ssm+jpa+thymeleaf+html)
很多同学都有自己的网盘,方便存储一些java学习教程。该毕业设计实现了一个简易的网盘,包含文件上传和文件分享等功能。 后端技术采用了spring,spring mvc,JPA,前端采用了thymeleaf模板语言。整体业务功能相对不是太复杂,亮点是文件分享功能。
/**
* 文件管理
*
*
*/
@Controller
public class FileController {
public static String fileRootPath;
public static String tempPath; // 分块文件临时存储地址
// 文件、文件夹 移动 文件夹移动时fileName=@dir@
@RequestMapping(value = "/filemove", produces = "application/json; charset=utf-8")
@ResponseBody
public ResponseMsg fileMove(String fileName, String oldPath, String newPath, HttpServletRequest request) {
if (fileName == null) {
fileName = "@dir@";
}
ResponseMsg j = new ResponseMsg();
if (oldPath.isEmpty() || newPath.isEmpty()) {
j.setMsg("路径名字为空!");
return j;
}
// 获取用户名
String userName = WebUtil.getUserNameByRequest(request);
// 移动文件
boolean b = fileService.userFileDirMove(fileName, oldPath, newPath, userName);
if (b) {
j.setSuccess(true);
j.setMsg("移动成功!");
} else {
j.setMsg("移动失败!");
}
return j;
}
/**
* 分块上传 有断点续传的功能
*
* @param request
* @param response
* @param file
* @param path
*/
@RequestMapping(value = "/uploadsevlet", method = RequestMethod.POST)
@ResponseBody
public void uploadSevlet(HttpServletRequest request, HttpServletResponse response, MultipartFile file,
String path) {
// String fileMd5 = request.getParameter("fileMd5");
String chunk = request.getParameter("chunk");
logger.warn("chunk:" + chunk);
String fileName = file.getOriginalFilename();
String userName = WebUtil.getUserNameByRequest(request);
MultipartHttpServletRequest Murequest = (MultipartHttpServletRequest) request;
Map<String, MultipartFile> files = Murequest.getFileMap();
logger.warn("执行前---------");
if (null != files && !files.isEmpty()) {
for (MultipartFile item : files.values()) {
String tempDir = FileUtil.getTempDir(tempPath, userName, fileName);
tempDir = StringUtil.stringSlashToOne(tempDir);
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) {
}
}
/**
* 主要页面映射
*
*
*/
@Controller
public class IndexController {
private Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* 管理页面
*
* @return 页面
*/
@RequestMapping("/main")
public ModelAndView admin(HttpServletRequest request) {
User user = (User) request.getSession().getAttribute("user");
String userName = user.getUserName();
ModelAndView modelAndView = new ModelAndView("main");
modelAndView.addObject("author", userName);
return modelAndView;
}
User user = (User) request.getSession().getAttribute("user");
if (user == null) {
//未登录,跳转到登录界面,登录之后默认保存到网盘连接的地址<a href="wut://pan">链接到app</a>
j.setMsg("未登录");
j.setSuccess(false);
} else {
j.setMsg("已登录");
j.setSuccess(true);
}
return j;
}
}
/**
*
flag = true;
}
}
return flag;
}
@Override
public void postHandle(HttpServletRequest request, HttpServletResponse response, Object handler,
ModelAndView modelAndView) {
if (handler instanceof HandlerMethod) {
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
long startTime = (Long) request.getAttribute("requestStartTime");
long endTime = System.currentTimeMillis();
long executeTime = endTime - startTime;
// 打印方法执行时间
if (executeTime > 1000) {
logger.warn(
"[" + method.getDeclaringClass().getName() + "." + method.getName() + "] 执行耗时 : " + executeTime
+ "ms");
} else {
logger.warn("[" + method.getDeclaringClass().getSimpleName() + "." + method.getName() + "] 执行耗时 : "
+ executeTime + "ms");
}
}
}
@Override
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) {
}
}
if (namelist.contains(fileMsg.getName().substring(0, suffixidx) + "mp4")) {
Map<String, Object> map = FfmpegUtil.ffmpegTaskMap.get(fileMsg.getLink());
// 含有转码文件且有转码记录
if (null != map) {
String transcode = (String) map.get("flag");
fileMsg.setTranscode(transcode);
}
// 含有转码文件但没有转码记录,说明之前已完成转码
else {
fileMsg.setTranscode("complete");
}
}
// 没有转码文件说明可转码
else {
fileMsg.setTranscode("transcodable");
}
}
}
return fileMsgList;
}
// 用户根目录文件列出
@RequestMapping(value = "/userfilelist", produces = "application/json; charset=utf-8")
@ResponseBody
public List<FileMsg> userFileList(@RequestParam(required = false) String key, String path,
HttpServletRequest request) {
if (path == null) {
path = "/";
}
// 获取用户名
String userName = WebUtil.getUserNameByRequest(request);
// 列出用户文件
List<FileMsg> fileMsgList = fileService.userFileList(userName, path);
// 判断文件转码情况
for (FileMsg fileMsg : fileMsgList) {
// 跳过文件夹
if (fileMsg.getSize().equals("Directory")) {
continue;
}
// 正常文件
int suffixidx = (int) StringUtil.getfilesuffix(fileMsg.getName(), true);
String suffix = fileMsg.getName().substring(suffixidx);
if (suffix.equals("mkv") || suffix.equals("rmvb") || suffix.equals("avi") || suffix.equals("wmv")
|| suffix.equals("3gp") || suffix.equals("rm")) {
// 取非文件夹的所有文件名
List<String> namelist = fileMsgList.stream()
.filter(f -> !f.getSize().equals("Directory"))
.map(FileMsg::getName)
.collect(Collectors.toList());
// 含有转码文件的情况下
if (namelist.contains(fileMsg.getName().substring(0, suffixidx) + "mp4")) {
Map<String, Object> map = FfmpegUtil.ffmpegTaskMap.get(fileMsg.getLink());
String encryptedPwd = Md5SaltTool.getEncryptedPwd(password);
user.setPassWord(encryptedPwd);
} catch (NoSuchAlgorithmException e) {
logger.error("NoSuchAlgorithmException:", e);
} catch (UnsupportedEncodingException e) {
logger.error("UnsupportedEncodingException:", e);
}
}
if (email != null) {
user.setEmail(email);
}
if (phone != null) {
user.setPhone(phone);
}
userService.update(user);
j.setMsg("更新用户信息成功!");
j.setSuccess(true);
return j;
}
//检查是否是登录状态
@RequestMapping(value = "/islogin")
@ResponseBody
public ResponseMsg isLogin(@RequestParam(required = false) String savePath, HttpServletRequest request) {
if (savePath == null) {
savePath = "/";
}
ResponseMsg j = new ResponseMsg();
// 获取用户名
User user = (User) request.getSession().getAttribute("user");
if (user == null) {
//未登录,跳转到登录界面,登录之后默认保存到网盘连接的地址<a href="wut://pan">链接到app</a>
j.setMsg("未登录");
j.setSuccess(false);
} else {
j.setMsg("已登录");
j.setSuccess(true);
}
return j;
}
}
/**
* 文件根目录
*/
@Value("${fileRootPath}")
private String root;
/**
* file业务处理bean
*/
@Autowired
private IFileService fileService;
/**
* 文件上传
*
* @param path 上传路径
* @param request Servlet3.0方式上传文件,获取parts
* @return result
*/
@RequestMapping("upload")
public ResponseMsg upload(@RequestParam String path, HttpServletRequest request) {
try {
// Servlet3.0方式上传文件
Collection<Part> parts = request.getParts();
for (Part part : parts) {
// 忽略路径字段,只处理文件类型
if (part.getContentType() != null) {
String fullPath = root + "sandeepin/" + path;
System.out.println("fullPath:" + fullPath);
File f = new File(fullPath, FileUtil.getFileNameByContentDisposition(part.getHeader("content-disposition")));
if (!FileUtil.writeInputStreamToFile(part.getInputStream(), f)) {
throw new Exception("文件上传失败");
}
}
}
return new ResponseMsg("upload successful!");
} catch (Exception e) {
return new ResponseMsg();
}
}
/**
* 空间占用展示
*
// String userName ="zc";
// 下载文件,获取下载路径,这个是 个映射的路径
String link = fileService.download(fileName, userName, path);
try {
//这里校验要填真实的路经
String newLink = link.replace("/data/", fileRootPath);
String[] md5Array = FileSplit.splitBySizeSubSection(newLink, size,
fileRootPath + "/tempMd5/" + userName + "/");
j.setObj(md5Array);
} catch (Exception e) {
logger.error("Exception:", e);
j.setObj("");
}
if (!link.isEmpty()) {
j.setSuccess(true);
j.setMsg(link);
} else {
j.setMsg("");
logger.warn("下载失败");
}
return j;
}
// 搜索接口
@RequestMapping(value = "/search", produces = "application/json; charset=utf-8")
@ResponseBody
public List<FileMsg> search(@RequestParam String key, String path, HttpServletRequest request) {
if (path == null) {
path = "/";
}
// 获取用户名
String userName = WebUtil.getUserNameByRequest(request);
List<FileMsg> fileMsgList = fileService.search(key, userName, path);
// 判断文件转码情况
for (FileMsg fileMsg : fileMsgList) {
// 跳过文件夹
if (fileMsg.getSize().equals("Directory")) {
continue;
}
// 正常文件
int suffixidx = (int) StringUtil.getfilesuffix(fileMsg.getName(), true);
}
return new ResponseMsg(renameMsg.getAfter());
}
/**
* 删除文件或目录(批量)
*
* @param dirMsgList 路径、目录名jsonList
* @param request HttpServletRequest
* @return ResponseMsg
*/
@DeleteMapping(value = "/delete", produces = "application/json; charset=utf-8")
public ResponseMsg delete(@RequestBody List<DirMsg> dirMsgList, HttpServletRequest request) {
String userName = WebUtil.getUserNameByRequest(request);
dirMsgList.forEach(e -> {
String path = e.getPath() + "/" + e.getName();
logger.warn("delete() file:{}", path);
try {
FileUtils.forceDelete(new File(root + userName + "/" + path));
} catch (IOException ex) {
logger.error("delete() IOException! file:{}", path);
}
});
return new ResponseMsg("delete successful.");
}
/**
* 移动文件或目录(批量)
*
* @param msgList 移动前后的名字jsonList
* @param request HttpServletRequest
* @return ResponseMsg
*/
@PutMapping(value = "/move", produces = "application/json; charset=utf-8")
public ResponseMsg move(@RequestBody List<RenameMsg> msgList, HttpServletRequest request) {
String userName = WebUtil.getUserNameByRequest(request);
msgList.forEach(e -> {
String msg = e.getBefore() + " to " + e.getAfter();
logger.warn("move() file:{}", msg);
try {
// todo
FileUtils.forceDelete(new File(root + userName + "/" + msg));
} catch (IOException ex) {
logger.error("delete() IOException! file:{}", msg);
}
});
}
return new ResponseMsg(renameMsg.getAfter());
}
/**
* 删除文件或目录(批量)
*
* @param dirMsgList 路径、目录名jsonList
* @param request HttpServletRequest
* @return ResponseMsg
*/
@DeleteMapping(value = "/delete", produces = "application/json; charset=utf-8")
public ResponseMsg delete(@RequestBody List<DirMsg> dirMsgList, HttpServletRequest request) {
String userName = WebUtil.getUserNameByRequest(request);
dirMsgList.forEach(e -> {
String path = e.getPath() + "/" + e.getName();
logger.warn("delete() file:{}", path);
try {
FileUtils.forceDelete(new File(root + userName + "/" + path));
} catch (IOException ex) {
logger.error("delete() IOException! file:{}", path);
}
});
return new ResponseMsg("delete successful.");
}
/**
* 移动文件或目录(批量)
*
* @param msgList 移动前后的名字jsonList
* @param request HttpServletRequest
* @return ResponseMsg
*/
@PutMapping(value = "/move", produces = "application/json; charset=utf-8")
public ResponseMsg move(@RequestBody List<RenameMsg> msgList, HttpServletRequest request) {
String userName = WebUtil.getUserNameByRequest(request);
msgList.forEach(e -> {
String msg = e.getBefore() + " to " + e.getAfter();
logger.warn("move() file:{}", msg);
try {
// todo
FileUtils.forceDelete(new File(root + userName + "/" + msg));
} catch (IOException ex) {
logger.error("delete() IOException! file:{}", msg);
}
// 获取用户名
String userName = WebUtil.getUserNameByRequest(request);
// 上传文件
boolean b = fileService.upload(file, userName, path);
// 反馈用户信息
if (b) {
j.setSuccess(true);
j.setMsg("上传成功!");
} else {
j.setMsg("上传失败!");
}
return j;
}
// 文件下载
@RequestMapping(value = "/download", produces = "application/json; charset=utf-8")
@ResponseBody
public ResponseMsgAdd download(@RequestParam String fileName, String path, HttpServletRequest request) {
if (path == null) {
path = "/";
}
ResponseMsgAdd j = new ResponseMsgAdd();
if (fileName.isEmpty()) {
j.setMsg("文件名字为空!");
return j;
}
// 获取用户名
String userName = WebUtil.getUserNameByRequest(request);
// String userName ="zc";
// 下载文件,获取下载路径,这个是 个映射的路径
String link = fileService.download(fileName, userName, path);
try {
//这里校验要填真实的路经
String newLink = link.replace("/data/", fileRootPath);
String[] md5Array = FileSplit.splitBySizeSubSection(newLink, size,
fileRootPath + "/tempMd5/" + userName + "/");
j.setObj(md5Array);
} catch (Exception e) {
logger.error("Exception:", e);
j.setObj("");
}
if (!link.isEmpty()) {
j.setSuccess(true);
public void afterCompletion(HttpServletRequest request, HttpServletResponse response, Object handler,
Exception ex) {
}
}
/**
* 主要页面映射
*
*
*/
@Controller
public class IndexController {
private Logger logger = LoggerFactory.getLogger(this.getClass());
/**
* 管理页面
*
* @return 页面
*/
@RequestMapping("/main")
public ModelAndView admin(HttpServletRequest request) {
User user = (User) request.getSession().getAttribute("user");
String userName = user.getUserName();
ModelAndView modelAndView = new ModelAndView("main");
modelAndView.addObject("author", userName);
return modelAndView;
}
/**
* onlineplayer页面
*
* @return 页面
*/
@RequestMapping("/onlineplayer")
public ModelAndView onlineplayer(HttpServletRequest request, String fileName, String filePath) {
User user = (User) request.getSession().getAttribute("user");
String userName = (user==null)?"null":user.getUserName();
ModelAndView modelAndView = new ModelAndView("onlineplayer");
modelAndView.addObject("author", userName);
modelAndView.addObject("fileName", fileName);
modelAndView.addObject("filePath", filePath);
return modelAndView;
@ResponseBody
public ResponseMsg dirCreate(String dirName, String path, HttpServletRequest request) {
if (path == null) {
path = "/";
}
ResponseMsg j = new ResponseMsg();
if (dirName.isEmpty() || path.isEmpty()) {
j.setMsg("文件夹名字为空!");
return j;
}
// 获取用户名
String userName = WebUtil.getUserNameByRequest(request);
// path = /pan/userName/当前path
if (!SystemUtil.isWindows()) {
path = "/pan/" + userName + path;
} else {
path = fileRootPath + userName + path;
}
// 重命名文件
boolean b = fileService.userDirCreate(dirName, path);
if (b) {
j.setSuccess(true);
j.setMsg("文件夹创建成功!");
} else {
j.setMsg("文件夹创建失败!");
}
return j;
}
// 文件提取码->真实地址(验证提取码是否正确)
@RequestMapping(value = "/shareCallBack", produces = "application/json; charset=utf-8")
@ResponseBody
public ResponseMsg shareCallBack(String link) {
logger.warn("执行shareCallBack接口!:" + link);
ResponseMsg j = new ResponseMsg();
if (link.isEmpty()) {
j.setMsg("提取码为空!");
return j;
}
String downloadLink = fileService.fileShareCodeDecode(link);
logger.warn("downloadLink:" + downloadLink);
if (!"null".equals(downloadLink)) {
j.setSuccess(true);
/**
* 文件管理
*
*
*/
@Controller
public class FileController {
public static String fileRootPath;
public static String tempPath; // 分块文件临时存储地址
//MD5文件的大小
public static int size;
private static int secretLen;
// 秘钥
private static String key;
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Autowired
private IFileService fileService;
@Autowired
private LinkSecretServiceImpl linkSecretService;
@Autowired
private SaveServiceImpl saveService;
@Value("${key}")
public void setKey(String key) {
FileController.key = key;
}
@Value("${tempPath}")
public void setTempPath(String tempPath) {
FileController.tempPath = tempPath;
}
@Value("${fileRootPath}")
public void setFileRootPath(String fileRootPath) {
responseMsg.setSuccess(result);
if (result) {
responseMsg.setMsg(registerCode);
} else {
responseMsg.setMsg("生成注册码失败,请重新操作!");
}
return responseMsg;
}
}
/**
* 拦截配置
*
*
*/
public class WebInterceptor implements HandlerInterceptor {
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Override
public boolean preHandle(HttpServletRequest request, HttpServletResponse response, Object handler)
throws Exception {
boolean flag = true;
if (handler instanceof HandlerMethod) {
String ip = request.getRemoteAddr();
long startTime = System.currentTimeMillis();
request.setAttribute("requestStartTime", startTime);
HandlerMethod handlerMethod = (HandlerMethod) handler;
Method method = handlerMethod.getMethod();
logger.warn("用户ip:" + ip + ",访问目标:" + method.getDeclaringClass().getName() + ":" + method.getName());
}
@RequestMapping(value = "/sharefileSecret", produces = "application/json; charset=utf-8")
@ResponseBody
public ResponseMsg shareFileSecret(String link, String secret, HttpServletRequest request,
HttpServletResponse response) {
logger.warn("执行sharefileSecret接口");
String downloadLink = "";
Map<Object, String> map = new HashMap<>();
if (!link.isEmpty()) {
// downloadLink= fileService.fileShareCodeDecode(link);
downloadLink = link;
}
//在数据库查找这个链接
LinkSecret linkSecret = linkSecretService.findLinkSecretBysecretLink(downloadLink);
String secret1 = linkSecret.getSecret();
if (secret1.toLowerCase().equals(secret.toLowerCase())) {
linkSecretService.addOneToDownloadNum(linkSecret);
logger.warn("密码正确!");
logger.warn("codeArray[1]路径:" + link);
ResponseMsg responseMsg = new ResponseMsg();
responseMsg.setSuccess(true);
responseMsg.setMsg(link);
return responseMsg;
} else {
logger.warn("密码不正确!");
ResponseMsg responseMsg = new ResponseMsg();
responseMsg.setSuccess(false);
responseMsg.setMsg("密码不正确!");
return responseMsg;
}
}
// 文件提取码生成,当再次分享同一个文件,只更新过期时间
@RequestMapping(value = "/generateShareLink", produces = "application/json; charset=utf-8")
@ResponseBody
public ResponseMsg generateShareLink(@RequestParam String expireDay, String fileName, String path,
HttpServletRequest request) {
String expireDayString = expireDay;
int expireDays = 3;
if (expireDayString != null) {
if (expireDayString.equals("永久有效")) {
expireDays = -1;
} else {
expireDays = Integer.parseInt(expireDayString);
}
}
if (path == null) {
path = "/";
}
ResponseMsg j = new ResponseMsg();
if (fileName.isEmpty() || path.isEmpty()) {
@Value("${size}")
public void setSize(int size) {
FileController.size = size;
}
// 文件上传
@RequestMapping(value = "/upload", produces = "application/json; charset=utf-8")
@ResponseBody
public ResponseMsg upload(@RequestParam MultipartFile file, String path, HttpServletRequest request) {
if (path == null) {
path = "/";
}
ResponseMsg j = new ResponseMsg();
if (file.isEmpty()) {
j.setMsg("请选择要上传的文件!");
return j;
}
// 获取用户名
String userName = WebUtil.getUserNameByRequest(request);
// 上传文件
boolean b = fileService.upload(file, userName, path);
// 反馈用户信息
if (b) {
j.setSuccess(true);
j.setMsg("上传成功!");
} else {
j.setMsg("上传失败!");
}
return j;
}
// 文件下载
@RequestMapping(value = "/download", produces = "application/json; charset=utf-8")
@ResponseBody
public ResponseMsgAdd download(@RequestParam String fileName, String path, HttpServletRequest request) {
if (path == null) {
path = "/";
}
ResponseMsgAdd j = new ResponseMsgAdd();
if (fileName.isEmpty()) {
j.setMsg("文件名字为空!");
return j;
}
// 获取用户名
String userName = WebUtil.getUserNameByRequest(request);
// String userName ="zc";
// 下载文件,获取下载路径,这个是 个映射的路径
String link = fileService.download(fileName, userName, path);
try {