自己動手用Springboot實現(xiàn)仿百度網(wǎng)盤的實踐
項目編號:BS-PT-032
本項目基于Springboot開發(fā)實現(xiàn),前端采用BootStrap開發(fā)實現(xiàn),系統(tǒng)功能完整,交互性好,模仿百度網(wǎng)盤實現(xiàn)相關(guān)功能,比較適合做畢業(yè)設(shè)計使用,創(chuàng)意性強。
開發(fā)工具為IDEA或ECLIPSE,數(shù)據(jù)庫采用MYSQL數(shù)據(jù)庫。
系統(tǒng)部分功能展示如下:
http://localhost:8080/toLogin admin / 123456
登陸頁面:

主頁

對應(yīng)本地磁盤存儲目錄:

分享網(wǎng)盤資料

根據(jù)提取碼下載相關(guān)資料

下載

重命名文件或文件夾

文件上傳

新建文件夾

上傳音樂文件后可以一鍵自動播放

以上是本系統(tǒng)的部分展示功能,可以做為畢業(yè)設(shè)計使用。
部分代碼實現(xiàn)如下:
package com.bjpowernode.pan.service.impl;
import com.bjpowernode.pan.dao.model.LinkSecret;
import com.bjpowernode.pan.model.FileMsg;
import com.bjpowernode.pan.service.IFileService;
import com.bjpowernode.pan.util.*;
import org.apache.commons.io.FileUtils;
import org.slf4j.Logger;
import org.slf4j.LoggerFactory;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.beans.factory.annotation.Value;
import org.springframework.stereotype.Service;
import org.springframework.web.multipart.MultipartFile;
import java.io.*;
import java.nio.channels.FileChannel;
import java.text.SimpleDateFormat;
import java.util.*;
/**
*指南針畢設(shè)
*/
@Service
public class FileServiceImpl implements IFileService {
public static String fileRootPath;
public static String tempPath; //分塊文件臨時存儲地址
// 自定義密鑰
static private String key;
@Autowired
SaveServiceImpl saveService;
@Autowired
LinkSecretServiceImpl linkSecretService;
private Logger logger = LoggerFactory.getLogger(this.getClass());
@Value("${tempPath}")
public void setTempPath(String tempPath) {
FileServiceImpl.tempPath = tempPath;
}
@Value("${fileRootPath}")
public void setFileRootPath(String fileRootPath) {
FileServiceImpl.fileRootPath = fileRootPath;
}
@Value("${key}")
public void setKey(String key) {
FileServiceImpl.key = key;
}
@Override
public boolean upload(MultipartFile file, String userName, String path) {
boolean b = false;
// 服務(wù)器上傳的文件所在路徑
String saveFilePath = fileRootPath + userName + "/" + path;
logger.warn("1 saveFilePath:" + saveFilePath);
// 判斷文件夾是否存在-建立文件夾
File filePathDir = new File(saveFilePath);
if (!filePathDir.exists()) {
filePathDir.mkdir();
}
// 獲取上傳文件的原名 例464e7a80_710229096@qq.com.zip
String saveFileName = file.getOriginalFilename();
// 上傳文件到-磁盤
try {
FileUtils.copyInputStreamToFile(file.getInputStream(), new File(saveFilePath, saveFileName));
b = true;
} catch (Exception e) {
logger.error("Exception:", e);
return false;
}
return b;
}
@Override
public String download(String fileName, String userName, String path) {
// 服務(wù)器下載的文件所在的本地路徑的文件夾
String saveFilePath = fileRootPath + userName + "/" + path;
logger.warn("1 saveFilePath:" + saveFilePath);
// 判斷文件夾是否存在-建立文件夾
File filePathDir = new File(saveFilePath);
if (!filePathDir.exists()) {
filePathDir.mkdir();
}
// 本地路徑
saveFilePath = saveFilePath + "/" + fileName;
String link = saveFilePath.replace(fileRootPath, "/data/");
link = StringUtil.stringSlashToOne(link);
logger.warn("返回的路徑:" + link);
return link;
}
@Override
public List<FileMsg> userFileList(String userName, String path) {
logger.warn("執(zhí)行userFileList函數(shù)!");
List<FileMsg> fileMsgList = new ArrayList<>();
// 拉取文件列表-本地磁盤
String webSaveFilePath = fileRootPath + userName + "/" + path;
File files = new File(webSaveFilePath);
if (!files.exists()) {
return fileMsgList;
}
File[] tempList = files.listFiles();
if (tempList == null) {
return fileMsgList;
}
for (File file : tempList) {
if (file.isFile()) {
FileMsg fileMsg = new FileMsg();
// 獲取文件名和下載地址
String link = file.toString().replace("\\", "/");
String[] nameArr = link.split("/");
String name = nameArr[nameArr.length - 1];
link = link.replace(fileRootPath, "/data/");
link = link.replace("/root/pan/", "/data/");
String size = FileUtil.fileSizeToString(file.length());
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String lastModTime = formatter.format(file.lastModified());
// 賦值到j(luò)son
fileMsg.setName(name);
fileMsg.setLink(link);
fileMsg.setSize(size);
fileMsg.setTime(lastModTime);
if (FileUtil.isMp4(name)) {
fileMsg.setType("mp4");
} else if (FileUtil.isVideo(name)) {
fileMsg.setType("video");
} else {
fileMsg.setType("file");
}
fileMsgList.add(fileMsg);
} else {
FileMsg fileMsg = new FileMsg();
String link = file.toString().replace("\\", "/");
String[] nameArr = link.split("/");
String name = nameArr[nameArr.length - 1];
String dirPath = link.replace(fileRootPath + userName, "");
if (!name.equals("userIcon")) {
fileMsg.setName(name);
fileMsg.setSize("Directory");
fileMsg.setType("dir");
fileMsg.setLink(dirPath);
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String lastModTime = formatter.format(file.lastModified());
fileMsg.setTime(lastModTime);
fileMsgList.add(fileMsg);
}
}
}
//排序
ListUtil.listSort(fileMsgList);
return fileMsgList;
}
/**
* 展示path目錄下的全部文件信息
*
* @param path 文件完全路徑
* @param userName 用戶名
* @return FileMsg List
*/
@Override
public List<FileMsg> list(String path, String userName) {
List<FileMsg> fileMsgList = new ArrayList<>();
File files = new File(path);
if (!files.exists()) {
return fileMsgList;
}
File[] tempList = files.listFiles();
if (tempList == null) {
return fileMsgList;
}
// 遍歷每個文件轉(zhuǎn)json對象
for (File file : tempList) {
fileMsgList.add(FileUtil.fileToFileMsg(file, userName, fileRootPath, "/data/"));
}
// 排序規(guī)則:文件夾在前,文件在后,更新時間最近的在前
ListUtil.listSort(fileMsgList);
return fileMsgList;
}
@Override
public Boolean[] userFileDelete(String fileName, String userName, String path) {
//解析fileName: 以$$符號分割
String[] fileNames = null;
if (fileName.contains("$$")) {
fileNames = fileName.split("\\$\\$");
} else {
fileNames = new String[1];
fileNames[0] = fileName;
}
Boolean[] b = new Boolean[fileNames.length];
for (int i = 0; i < fileNames.length; i++) {
// 刪除-本地文件
String saveFilePath = fileRootPath + userName + "/" + path;
File file = new File(saveFilePath);
File[] listFiles = file.listFiles();
boolean b1 = false;
//判斷是否是文件夾
if (fileName.equals("@dir@")) {
//是文件夾
b1 = FileUtil.delete(saveFilePath);
} else {
b1 = FileUtil.delete(saveFilePath + "/" + fileNames[i]);
}
// if (!b1){
// FileSave fileSave=saveService.findFileSaveByUserNameAndFileName(userName,
// fileNames[i]);
// saveService.delete(fileSave);
// b1=true;
// }
b[i] = b1;
}
return b;
}
@Override
public boolean userFileRename(String oldName, String newName, String userName, String path) {
// 重命名-本地磁盤文件
String oldNameWithPath;
String newNameWithPath;
if ("@dir@".equals(oldName)) {
oldNameWithPath = StringUtil.stringSlashToOne(fileRootPath + userName + "/" + path);
newNameWithPath =
oldNameWithPath.substring(0, (int) StringUtil.getfilesuffix(oldNameWithPath, true, "/")) + "/" + newName;
newNameWithPath = StringUtil.stringSlashToOne(newNameWithPath);
} else {
oldNameWithPath = StringUtil.stringSlashToOne(fileRootPath + userName + "/" + path + "/" + oldName);
newNameWithPath = StringUtil.stringSlashToOne(fileRootPath + userName + "/" + path + "/" + newName);
}
return FileUtil.renameFile(oldNameWithPath, newNameWithPath);
}
@Override
public boolean userDirCreate(String dirName, String path) {
File file = new File(path + "/" + dirName);
return file.mkdir();
}
@Override
public String fileShareCodeEncode(String filePathAndName) {
EncryptUtil des;
try {
des = new EncryptUtil(key, "utf-8");
return des.encode(filePathAndName);
} catch (Exception e) {
logger.error("Exception:", e);
}
return "null";
}
@Override
public String fileShareCodeDecode(String code) {
EncryptUtil des;
try {
des = new EncryptUtil(key, "utf-8");
logger.warn("00 code:" + code);
String filePathAndName = des.decode(code);
logger.warn("00 filePathAndName:" + filePathAndName);
String[] arr = filePathAndName.split("/");
LinkSecret linkSecret = linkSecretService.findLinkSecretBysecretLink(code);
String[] localLink = linkSecret.getLocalLink().split("/");
String userName = localLink[3];
// String userName = arr[0];
String fileName = arr[arr.length - 1];
arr[arr.length - 1] = "";
// String path = StringUtils.join(arr, "/");
String path = userName + "/";
if (localLink.length > 5) {
for (int k = 4; k < localLink.length - 1; k++) {
path = path + localLink[k] + "/";
}
}
logger.warn("0 userName:" + userName);
logger.warn("1 filePathAndName:" + filePathAndName);
logger.warn("2 fileName:" + fileName);
logger.warn("3 path:" + path);
// 服務(wù)器下載的文件所在的本地路徑的文件夾
String saveFilePath = fileRootPath + "share" + "/" + path;
// String saveFilePath = fileRootPath + "/" + path;
logger.warn("1 saveFilePath:" + saveFilePath);
// 判斷文件夾是否存在-建立文件夾
File filePathDir = new File(saveFilePath);
if (!filePathDir.exists()) {
// mkdirs遞歸創(chuàng)建父目錄
boolean b = filePathDir.mkdirs();
logger.warn("遞歸創(chuàng)建父目錄:" + b);
}
saveFilePath = fileRootPath + "/" + path + "/" + fileName;
String link = saveFilePath.replace(fileRootPath, "/data/");
link = StringUtil.stringSlashToOne(link);
logger.warn("4 link:" + link);
// 返回下載路徑
return link;
} catch (Exception e) {
logger.error("Exception:", e);
return "null";
}
}
@Override
public boolean userFileDirMove(String fileName, String oldPath, String newPath, String userName) {
// 移動-本地磁盤文件
String saveFilePath = fileRootPath + userName + "/";
String lfilename = ("@dir@".equals(fileName) ? "" : "/" + fileName);
String oldNameWithPath = StringUtil.stringSlashToOne(saveFilePath + oldPath + lfilename);
String tmpnewfilename = "@dir@".equals(fileName) ?
(String) StringUtil.getfilesuffix(oldNameWithPath, false, "/", false) : "";
String newNameWithPath = StringUtil.stringSlashToOne(saveFilePath + newPath + lfilename + tmpnewfilename);
return FileUtil.renameFile(oldNameWithPath, newNameWithPath);
}
@Override
public List<FileMsg> search(String key, String userName, String path) {
List<FileMsg> fileMsgList = new ArrayList<>();
// 拉取文件列表-本地磁盤
String webSaveFilePath = fileRootPath + userName + "/" + path;
File files = new File(webSaveFilePath);
if (!files.exists()) {
files.mkdir();
}
// File[] tempList = files.listFiles();
List<File> tempList = new ArrayList<>();
tempList = SearchFileByKey.searchFile(webSaveFilePath, key, false, tempList);
for (int i = 0; i < tempList.size(); i++) {
if (tempList.get(i).isFile()) {
// logger.warn("用戶:" + userName + " 文件:" + tempList[i]);
FileMsg fileMsg = new FileMsg();
// 獲取文件名和下載地址
String link = tempList.get(i).toString().replace("\\", "/");
String[] nameArr = link.split("/");
String name = nameArr[nameArr.length - 1];
link = link.replace(fileRootPath, "/data/");
link = link.replace("/root/pan/", "/data/");
String size = FileUtil.fileSizeToString(tempList.get(i).length());
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String lastModTime = formatter.format(tempList.get(i).lastModified());
// 賦值到j(luò)son
fileMsg.setName(name);
fileMsg.setLink(link);
fileMsg.setSize(size);
fileMsg.setTime(lastModTime);
fileMsgList.add(fileMsg);
} else {
FileMsg fileMsg = new FileMsg();
String link = tempList.get(i).toString().replace("\\", "/");
String[] nameArr = link.split("/");
String name = nameArr[nameArr.length - 1];
if (!name.equals("userIcon")) {
fileMsg.setLink(link);
fileMsg.setName(name);
fileMsg.setSize("Directory");
SimpleDateFormat formatter = new SimpleDateFormat("yyyy-MM-dd HH:mm:ss");
String lastModTime = formatter.format(tempList.get(i).lastModified());
fileMsg.setTime(lastModTime);
fileMsgList.add(fileMsg);
}
}
}
return fileMsgList;
}
@Override
public boolean merge(String fileName, String userName, String path) throws InterruptedException {
boolean b = false;
String savePath = fileRootPath + userName + "/" + path;
File saveDir = new File(savePath);
if (!saveDir.exists()) {
saveDir.mkdirs();
}
String tempDirPath = FileUtil.getTempDir(tempPath, userName, fileName);
File tempDir = new File(tempDirPath);
// 獲得分片文件列表
File[] fileArray = tempDir.listFiles(new FileFilter() {
// 只需要文件
@Override
public boolean accept(File pathname) {
if (pathname.isDirectory()) {
return false;
} else {
return true;
}
}
});
// logger.warn("【要合成的文件有】:"+fileArray);
// while (fileArray==null){
// }
// 轉(zhuǎn)成集合進行排序后合并文件
List<File> fileList = new ArrayList<File>(Arrays.asList(fileArray));
Collections.sort(fileList, new Comparator<File>() {
// 按文件名升序排列
@Override
public int compare(File o1, File o2) {
if (Integer.parseInt(o1.getName()) < Integer.parseInt(o2.getName())) {
return -1;
} else {
return 1;
}
}
});
// 目標文件
File outfile = new File(savePath + File.separator + fileName);
try {
outfile.createNewFile();
} catch (IOException e) {
b = false;
logger.warn("創(chuàng)建目標文件出錯:" + e.getMessage());
logger.error("Exception:", e);
}
// 執(zhí)行合并操作
FileChannel outChannel = null;
FileChannel inChannel;
try {
outChannel = new FileOutputStream(outfile).getChannel();
for (File file1 : fileList) {
inChannel = new FileInputStream(file1).getChannel();
inChannel.transferTo(0, inChannel.size(), outChannel);
inChannel.close();
file1.delete();
}
outChannel.close();
} catch (FileNotFoundException e) {
b = false;
logger.warn("合并分片文件出錯:" + e.getMessage());
logger.error("Exception:", e);
} catch (IOException e) {
b = false;
logger.warn("合并分片文件出錯:" + e.getMessage());
logger.error("Exception:", e);
}
// 刪除臨時文件夾 根目錄/temp/userName/fileName
File tempFileDir = new File(tempPath + File.separator + userName + File.separator + fileName);
FileUtil.deleteDir(tempFileDir);
return b;
}
//locallink是原始文件路徑,path:存取路徑
@Override
public boolean copyFileToMyPan(String userName, String localLink, String path) {
boolean b = false;
//share文件所在的地方
logger.warn("0 localLink:" + localLink);
localLink = localLink.replace("/data/", fileRootPath);
logger.warn("0.1 localLink2:" + localLink);
File oldfile = new File(localLink);
String[] msg = localLink.split("/");
String saveFileName = oldfile.getName();
String saveFilePath = fileRootPath + userName + "/" + path;
logger.warn("0.2 saveFilePath:" + saveFilePath);
File newfileDir = new File(saveFilePath);
if (!newfileDir.exists()) {
newfileDir.mkdir();
}
try {
if (oldfile.exists()) {
FileUtils.copyInputStreamToFile(new FileInputStream(oldfile), new File(saveFilePath, saveFileName));
b = true;
} else {
//TODO
logger.warn("存在同名文件");
b = false;
}
} catch (IOException e) {
logger.error("Exception:", e);
return false;
}
logger.warn("copyFileToMyPan() result:{}", b);
return b;
}
}
到此這篇關(guān)于自己動手用Springboot實現(xiàn)仿百度網(wǎng)盤的實踐的文章就介紹到這了,更多相關(guān)Springboot仿百度網(wǎng)盤內(nèi)容請搜索腳本之家以前的文章或繼續(xù)瀏覽下面的相關(guān)文章希望大家以后多多支持腳本之家!
相關(guān)文章
Java中實現(xiàn)Comparator接口和用法實例(簡明易懂)
這篇文章主要介紹了Java中實現(xiàn)Comparator接口和用法實例(簡明易懂),本文給出實現(xiàn)Comparator接口的實例和使用這個接口的代碼實例,需要的朋友可以參考下2015-05-05
SpringBoot集成ffmpeg實現(xiàn)視頻轉(zhuǎn)碼播放示例詳解
這篇文章主要為大家介紹了SpringBoot集成ffmpeg實現(xiàn)視頻轉(zhuǎn)碼播放示例詳解,有需要的朋友可以借鑒參考下,希望能夠有所幫助,祝大家多多進步,早日升職加薪2023-07-07
BeanDefinitionRegistryPostProcessor如何動態(tài)注冊Bean到Spring
這篇文章主要介紹了BeanDefinitionRegistryPostProcessor如何動態(tài)注冊Bean到Spring,具有很好的參考價值,希望對大家有所幫助。如有錯誤或未考慮完全的地方,望不吝賜教2022-03-03
spring boot整合Shiro實現(xiàn)單點登錄的示例代碼
本篇文章主要介紹了spring boot整合Shiro實現(xiàn)單點登錄的示例代碼,小編覺得挺不錯的,現(xiàn)在分享給大家,也給大家做個參考。一起跟隨小編過來看看吧2018-01-01
最簡單的在IntelliJ IDEA導入一個本地項目教程(圖文)
這篇文章主要介紹了最簡單的在IntelliJ IDEA導入一個本地項目教程(圖文),文中通過圖文介紹的非常詳細,對大家的學習或者工作具有一定的參考學習價值,需要的朋友們下面隨著小編來一起學習學習吧2020-08-08
關(guān)于SpringBoot中事務(wù)失效的幾種情況
這篇文章主要介紹了關(guān)于SpringBoot中事務(wù)失效的幾種情況,Spring AOP默認使用動態(tài)代理,會給被代理的類生成一個代理類,事務(wù)相關(guān)的操作都通過代理來完成,使用內(nèi)部方法調(diào)用時,使用的是實例調(diào)用,沒有通過代理類調(diào)用方法,因此事務(wù)不會檢測到失敗,需要的朋友可以參考下2023-08-08
Spring Data JPA中的Specification動態(tài)查詢詳解
Specification是一個設(shè)計模式,用于企業(yè)級應(yīng)用開發(fā)中,其主要目的是將業(yè)務(wù)規(guī)則從業(yè)務(wù)邏輯中分離出來,在數(shù)據(jù)查詢方面,Specification可以定義復(fù)雜的查詢,使其更易于重用和測試,這篇文章主要介紹了Spring Data JPA中的Specification動態(tài)查詢詳解,需要的朋友可以參考下2023-07-07

