1
0
mirror of https://gitee.com/bookshelfplus/bookshelfplus synced 2025-09-21 01:10:39 +08:00
Code Issues Projects Releases Wiki Activity GitHub Gitee

Merge branch 'big-change' into develop

This commit is contained in:
2022-04-20 20:23:31 +08:00
28 changed files with 690 additions and 943 deletions

View File

@@ -215,43 +215,7 @@
<hr>
<div class="download-container">
<h3 id="scrollTarget">下载这本书</h3>
<div id="file-container"><% /*
<!-- <div class="file-item">
<div class="file-title">
<span class="file-name size20">bookshelf</span><span class="file-ext size16">.json</span>
<span class="file-size size14" style="padding-left: 30px;">10.02MB</span>
</div>
<div class="file-detail">
<span class="size14 overflow-hide">SHA1<span class="file-sha1 size12">07b12eb2a5915282bf086a7913b0fd9720fc012c</span></span>
<span class="file-copyright size14 overflow-hide">来源信息:中国地质大学(武汉)</span>
<span class="file-copyright size14" style="margin-top: 12px; display: block;">下载方式:</span>
</div>
<div class="file-object">
<div class="file-object-item">
<div class="file-object-item-title">
<img src="/assets/image/svg/baidu_netdisk.svg"/>
<span>百度网盘</span>
</div>
<div class="file-object-item-content">
提取码abcd
</div>
<div class="file-object-item-link">
<a href="" target="_blank">百度网盘</a>
</div>
<div class="outdated-feedback">
<img src="/assets/image/svg/feedback.svg"/>
<span class="outdated-feedback-tip">链接失效?点击反馈!</span>
</div>
</div>
<div class="file-object-item">
<a href="" target="_blank">阿里云盘</a>
</div>
<div class="file-object-item">
<a href="" download="文件名.pdf">直链下载</a>
</div>
</div>
</div> --> */ %>
</div>
<div id="file-container"></div>
</div>
<p style="font-size: 12px;">
* 由于直链下载成本很高,为降低运营成本,目前仅提供给登录用户使用。
@@ -466,14 +430,14 @@
}
function getLinkDOM(fileObjectInfo) {
// 获取文件下载链接DOM
var iconSrc = "/assets/image/svg/direct_link.svg", title = fileObjectInfo.storageMediumType, content = "", downloadLink = "";
var iconSrc = "/assets/image/svg/direct_link.svg", title = fileObjectInfo.storageMedium, content = "", downloadLink = "";
if(fileObjectInfo.fileShareCode != "" && fileObjectInfo.fileShareCode != null) {
content = `<span>提取码: <span class="click2copy" style="user-select: all; cursor: pointer;">${fileObjectInfo.fileShareCode}</span>&nbsp;</span>`; // 最后一个 &nbsp; 是为了保证选中时不会选中后面的回车
downloadLink = `<a class="baiduNetdiskLink" share-code="${fileObjectInfo.fileShareCode}" share-link="${fileObjectInfo.filePath}" style="cursor: pointer;" title="复制提取码并前往">前往</a>`;
} else {
downloadLink = `<a href="${fileObjectInfo.filePath}" target="_blank">前往</a>`;
}
switch (fileObjectInfo.storageMediumType) {
switch (fileObjectInfo.storageMedium) {
case "腾讯云对象存储":
title = "直链下载";
if (!localStorageUtils.getLoginStatus()) {
@@ -490,7 +454,7 @@
iconSrc = "/assets/image/svg/aliyun_drive.svg";
break;
default:
title = fileObjectInfo.storageMediumType;
title = fileObjectInfo.storageMedium;
downloadLink = `<a href="${fileObjectInfo.filePath}" target="_blank">前往</a>`;
break;
}
@@ -530,29 +494,29 @@
// 再处理文件
var fileContainer = document.getElementById("file-container");
var innerHTML = [];
var innerHtmlList = [];
for (let i = 0; i < data.file.length; i++) {
const fileInfo = data.file[i];
innerHTML.push(`
innerHtmlList.push(`
<div class="file-item">
<div class="file-title">
<span class="file-name size20">${fileInfo.fileName}</span><span class="file-ext size16">${fileInfo.fileFormat == "" ? "" : ("." + fileInfo.fileFormat)}</span>
<span class="file-name size20">${fileInfo.fileName}</span><span class="file-ext size16">${fileInfo.fileExt == "" ? "" : ("." + fileInfo.fileExt)}</span>
<span class="file-size size14" style="padding-left: 30px;">${stringifyFileSize(fileInfo.fileSize)}</span>
</div>
<div class="file-detail">
<span class="overflow-hide file-sha1 size12">SHA1<span class="">${fileInfo.fileSha1}</span></span>
<span class="file-copyright size14 overflow-hide">${fileInfo.bookOrigin == "" ? "" : ("来源信息:" + fileInfo.bookOrigin) }</span>
<span class="file-copyright size14 overflow-hide">${fileInfo.source == "" ? "" : ("来源信息:" + fileInfo.source) }</span>
<span class="file-copyright size14" style="margin-top: 12px; display: block;">下载地址:</span>
</div>
<div class="file-object">
${fileObjectList[fileInfo.id] ? fileObjectList[fileInfo.id].join('') : ""}
${fileObjectList[fileInfo.id] ? fileObjectList[fileInfo.id].join('') : "暂无可用下载链接"}
</div>
</div>`
);
}
fileContainer.innerHTML = innerHTML.join("");
if (innerHTML.length == 0) {
fileContainer.innerHTML = innerHtmlList.join("");
if (innerHtmlList.length == 0) {
var fileItem = document.createElement("div");
fileItem.className = "file-item";
fileItem.style.textAlign = "center";

View File

@@ -1,6 +1,5 @@
<div class="searchBox">
<input id="searchInput" type="text" placeholder="只需两步:搜索、下载 就这么简单" /><!--
--><input id="searchButton" type="button" value="搜一下" />
</div>
<script>
@@ -45,13 +44,37 @@
});
// 搜索按钮点击事件
$('#searchButton').click(function () {
var searchBoxValue = $('#searchInput').val();
if (!searchBoxValue || searchBoxValue.trim() == "") {
// alert("请输入搜索内容");
// return;
window.location.href = "./search";
}
window.location.href = "./search?keyword=" + encodeURIComponent(searchBoxValue.trim());
});
if (location.pathname == "/" || !(window.history && history.pushState)) {
// 首页 或者不支持 history.pushState
$('#searchButton').click(function () {
var searchBoxValue = $('#searchInput').val();
if (!searchBoxValue || searchBoxValue.trim() == "") {
searchBoxValue = "";
}
window.location.href = "./search?keyword=" + encodeURIComponent(searchBoxValue.trim());
});
} else {
// 搜索页
$('#searchButton').click(function () {
var searchBoxValue = $('#searchInput').val();
// 如果搜索内容未变化,则不搜索
if (keyword == searchBoxValue.trim()) return;
if (!searchBoxValue || searchBoxValue.trim() == "") {
history.pushState({}, "", "./search"); // 第二个参数为保留参数
} else {
keyword = searchBoxValue.trim();
history.pushState({}, "", "./search?keyword=" + encodeURIComponent(keyword));
doSearch(keyword);
}
});
window.addEventListener('popstate', function (event) {
var requestParams = getParams();
var keyword = (requestParams["keyword"] || "").trim();
var searchbox = document.getElementById("searchInput");
searchbox.value = keyword;
doSearch(keyword);
});
}
</script>

View File

@@ -41,19 +41,26 @@
var renderData = [];
data.forEach(element => {
console.log(element);
var watermarkAndAdvertising = [];
if (element.watermark)
watermarkAndAdvertising.push("有水印");
if (element.advertising)
watermarkAndAdvertising.push("有广告");
watermarkAndAdvertising = watermarkAndAdvertising.join("") || "无";
renderData.push({
编号: `${element.id}`,
关联书籍: element.bookId === 0 ? "未关联书籍" : `<span class="overflow-omit" style="margin: 0 auto;">
关联书籍: element.bookId === 0 ? "<span style=\"font-size: 10px;\">未关联书籍</span>" : `<span class="overflow-omit" style="margin: 0 auto;">
ID: ${element.bookId}
<a href="/book?id=${element.bookId}">查看</a>
<a href="/dashboard/admin/book-manage/detail?id=${element.bookId}">修改</a>
</span>`,
文件名: `${element.fileDisplayName}`,
格式: `${element.fileFormat}`,
页数: `${element.numberOfPages}`,
水印: `${element.watermark}`,
广告: `${element.advertising}`,
来源: `<span class="overflow-omit" style="font-size: 10px;">${element.bookOrigin}</span>`,
文件名: `${element.fileName}`,
格式: `${element.fileExt}`,
页数: `${element.numberOfPages ?element.numberOfPages : ""}`,
"水印&广告": `<span style="font-size: 10px;">${watermarkAndAdvertising}</span>`,
来源: `<span class="overflow-omit" style="font-size: 10px;">${element.source}</span>`,
大小: `${element.fileSize}`,
"哈希(双击全选)": `<span class="overflow-omit" style="font-size: 10px;">${element.fileSha1}</span>`,
时间: `<span class="overflow-omit" style="font-size: 12px; line-height: 1.2em; display: block;"><nobr>

View File

@@ -1,10 +1,3 @@
<style>
/* 限制 哈希 列的宽度 */
tr>*:nth-child(8),
td>*:nth-child(8) {
max-width: 100px;
}
</style>
<p>
<a href="<%= pageUrl %>../">返回上一级</a>
&nbsp;
@@ -33,7 +26,6 @@
ID: ${element.fileId}
<a href="<%= pageUrl %>../detail?id=${element.fileId}">查看</a>
</span>`,
文件名: `${element.fileName}`,
修改日期: element.lastModified === 0 ? "未知" : `<span class="overflow-omit" style="font-size: 12px; line-height: 1.2em; display: block;"><nobr>
${new Date(element.lastModified).toISOString().replace(/T/, ' ').replace(/\..+/, '')}
</nobr></span>`,
@@ -45,9 +37,8 @@
提取码: ${element.fileShareCode}
</nobr></span>`,
存储介质: `<span class="overflow-omit" style="font-size: 12px; line-height: 1.2em; display: block;"><nobr>
${element.storageMediumType}
${element.storageMedium}
</nobr></span>`,
"哈希(双击全选)": `<span class="overflow-omit" style="font-size: 10px;">${element.fileSha1 ? element.fileSha1 : "未知"}</span>`,
状态: `${(element.uploadStatus ? element.uploadStatus : "<span style='color: grey; font-weight: bold;'>未知</span>")
.replace("SUCCESS", "<span style='color: green; font-weight: bold;'>成功</span>")
.replace("UPLOADING", "<span style='color: orange; font-weight: bold;'>正在上传</span>")

View File

@@ -374,9 +374,35 @@
if (status === "success") {
console.log("data", data);
// 取得预授权URL使用该URL进行文件上传
uploadFile(file, data.url, data.fileId);
uploadFile(file, data.url, data.fileId, data.fileObjectId);
} else {
alert(`出错啦!${data.errMsg} (错误码: ${data.errCode}) `);
if (data.errCode == "60001") {
// 文件已存在
console.log(`出错啦!${data.errMsg} (错误码: ${data.errCode}) `);
// 再次发送请求,查询这个已存在文件的 fileId
postRequest("/file/getFileByHash", { token: localStorageUtils.getToken(), fileSha1: fileInfo.fileSha1 })
.then(function (responseData) {
var axiosData = responseData.data;
var status = axiosData.status;
var data = axiosData.data;
if (status === "success") {
console.log(data);
// 查询到之后,询问用户是否跳转到文件详情页
var isRedirect = confirm(`文件已存在,是否前往查看详情?\n文件ID: ${data.id}`);
if (isRedirect)
location.href = `<%= pageUrl %>../detail?fileId=${data.id}`;
} else {
alert(`出错啦!${data.errMsg} (错误码: ${data.errCode}) `);
}
}).catch(function (error) {
console.log(error);
alert("无法连接到服务器,请检查网络连接!");
});
} else {
alert(`出错啦!${data.errMsg} (错误码: ${data.errCode}) `);
}
}
}).catch(function (error) {
console.log(error);
@@ -387,7 +413,7 @@
//##############################################
//传入预授权 URL ,将文件上传到这个地址
//##############################################
function uploadFile(file, preSignedUrl, fileId) {
function uploadFile(file, preSignedUrl, fileId, fileObjectId) {
// refer: https://cloud.tencent.com/document/product/436/35651
// 获取到 Url 后,前端可以这样 ajax 上传
@@ -408,13 +434,16 @@
console.log('上传成功', xhr.status, xhr.statusText);
// 等待进度条走到 100% 否则小文件进度条还没有走完就提示上传完成会让人感觉有点奇怪
setTimeout(function () {
alert("上传成功!");
if ($("#checkbox-auto-upload").is(":checked")) {
window.location.reload();
} else {
// location.href = "<%= pageUrl %>../";
location.href = "<%= pageUrl %>../detail?id=" + fileId;
}
// 上传成功触发一次 “刷新文件对象上传状态”,避免因为云函数回调不成功导致文件对象上传状态没有及时更新
refreshFileObjectStatus(fileObjectId, function () {
alert("上传成功!");
if ($("#checkbox-auto-upload").is(":checked")) {
window.location.reload();
} else {
// location.href = "<%= pageUrl %>../";
location.href = "<%= pageUrl %>../detail?id=" + fileId;
}
});
}, 300);
};
xhr.onerror = function (e) {
@@ -428,7 +457,7 @@
function getFileAssociatorList(fileSha1) {
var fileAssociator = document.getElementById("fileAssociator");
// 下拉框列表
postRequest("/file/list/MatchfileHash", { token: localStorageUtils.getToken(), fileSha1: fileSha1 })
postRequest("/file/list/MatchfileHashWithNullValue", { token: localStorageUtils.getToken(), fileSha1: fileSha1 })
.then(function (responseData) {
var axiosData = responseData.data;
var status = axiosData.status;
@@ -452,4 +481,25 @@
alert("无法连接到服务器,请检查网络连接!");
});
}
</script>
<script>
// 刷新文件对象上传状态
async function refreshFileObjectStatus(fileObjectId, callback) {
postRequest("/file/object/refreshFileObjectStatus", { token: localStorageUtils.getToken(), fileObjectId: fileObjectId })
.then(function (responseData) {
var axiosData = responseData.data;
var status = axiosData.status;
var data = axiosData.data;
if (status === "success") {
// console.log(data);
if (callback)
callback();
} else {
alert(`出错啦!${data.errMsg} (错误码: ${data.errCode}) `);
}
}).catch(function (error) {
console.log(error);
alert("无法连接到服务器,请检查网络连接!");
});
}
</script>

View File

@@ -52,11 +52,15 @@
searchbox.value = keyword;
if (keyword === "")
searchbox.focus();
search({
tableElementId: "result-table",
searchText: keyword,
categoryId: null
});
function doSearch(keyword) {
search({
tableElementId: "result-table",
searchText: keyword,
categoryId: null
});
}
doSearch(keyword);
</script>
</body>
</html>

View File

@@ -11,7 +11,7 @@
Target Server Version : 50726
File Encoding : 65001
Date: 19/04/2022 22:46:17
Date: 20/04/2022 16:15:38
*/
SET NAMES utf8mb4;
@@ -154,17 +154,16 @@ DROP TABLE IF EXISTS `file_info`;
CREATE TABLE `file_info` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增编号',
`book_id` int(11) NOT NULL,
`file_display_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`file_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`file_format` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`file_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '文件名(不含扩展名)',
`file_ext` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`file_size` bigint(20) UNSIGNED NOT NULL DEFAULT 0,
`file_sha1` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`number_of_pages` int(11) NOT NULL DEFAULT 0,
`watermark` tinyint(1) NOT NULL DEFAULT 0,
`advertising` tinyint(1) NOT NULL DEFAULT 0 COMMENT '1为已删除项',
`book_origin` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`source` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`file_create_at` datetime NOT NULL,
`file_modified_at` datetime NOT NULL ON UPDATE CURRENT_TIMESTAMP,
`file_size` bigint(20) UNSIGNED NOT NULL DEFAULT 0,
`file_sha1` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC;
@@ -179,17 +178,12 @@ DROP TABLE IF EXISTS `file_object_info`;
CREATE TABLE `file_object_info` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '编号',
`file_id` int(11) NOT NULL,
`file_name` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '文件名(不含扩展名',
`file_size` bigint(20) NOT NULL DEFAULT 0 COMMENT '文件大小',
`file_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '文件类型',
`storage_medium_type` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`upload_status` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '上传状态(上传成功 SUCCESS正在上传 UPLOADING上传终止 NOT_EXIST',
`storage_medium` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL,
`file_path` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '本地文件保存相对路径(本地维护用,非线上使用)',
`file_pwd` varchar(30) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`file_share_code` varchar(20) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
`upload_status` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '上传状态(上传成功 SUCCESS正在上传 UPLOADING上传终止 NOT_EXIST',
`file_sha1` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '' COMMENT '文件SHA1哈希',
`last_modified` bigint(20) UNSIGNED NOT NULL DEFAULT 0 COMMENT '文件最后修改时间戳',
`additional_fields` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_general_ci NOT NULL DEFAULT '',
PRIMARY KEY (`id`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_general_ci ROW_FORMAT = DYNAMIC;
@@ -197,28 +191,6 @@ CREATE TABLE `file_object_info` (
-- Records of file_object_info
-- ----------------------------
-- ----------------------------
-- Table structure for schedule_task
-- ----------------------------
DROP TABLE IF EXISTS `schedule_task`;
CREATE TABLE `schedule_task` (
`id` int(11) NOT NULL AUTO_INCREMENT COMMENT '自增id',
`create_time` datetime NOT NULL DEFAULT CURRENT_TIMESTAMP COMMENT '插入时间',
`schedule_time` datetime NOT NULL COMMENT '更新时间',
`action` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT '任务名称',
`data` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL DEFAULT '' COMMENT '数据字段',
`task_guid` varchar(255) CHARACTER SET utf8mb4 COLLATE utf8mb4_unicode_ci NOT NULL COMMENT 'GUID唯一标识',
`associated_user_id` int(11) NOT NULL COMMENT '和此任务关联的用户',
`fail_time` tinyint(4) NOT NULL DEFAULT 0 COMMENT '失败次数',
PRIMARY KEY (`id`) USING BTREE,
UNIQUE INDEX `task_guid`(`task_guid`) USING BTREE,
INDEX `schedule_time`(`schedule_time`) USING BTREE
) ENGINE = InnoDB AUTO_INCREMENT = 1 CHARACTER SET = utf8mb4 COLLATE = utf8mb4_unicode_ci ROW_FORMAT = Dynamic;
-- ----------------------------
-- Records of schedule_task
-- ----------------------------
-- ----------------------------
-- Table structure for third_party_user_auth_relation
-- ----------------------------

View File

@@ -11,4 +11,9 @@
<component name="ProjectRootManager" version="2" languageLevel="JDK_1_8" default="true" project-jdk-name="1.8" project-jdk-type="JavaSDK">
<output url="file://$PROJECT_DIR$/out" />
</component>
<component name="SwUserDefinedSpecifications">
<option name="specTypeByUrl">
<map />
</option>
</component>
</project>

View File

@@ -28,6 +28,9 @@ public enum BusinessErrorCode implements CommonError {
BOOK_FAVORITES_ALREADY_EXIST(50002, "书籍已经在收藏夹中"),
BOOK_FAVORITES_NOT_EXIST(50003, "书籍不在收藏夹中"),
// 60000开头为文件、文件对象相关错误定义
FILE_ALREADY_EXIST(60001, "文件已存在"),
// 占位
PLACE_HOLDER(99999, "这是一个占位符错误");

View File

@@ -85,11 +85,15 @@ public class QCloudCosUtils {
}
public Boolean doesObjectExist(String folder, String objectKey) {
return doesObjectExist(folder + objectKey);
}
public Boolean doesObjectExist(String filePath) {
COSClient cosClient = createCOSClient();
// 存储桶的命名格式为 BucketName-APPID此处填写的存储桶名称必须为此格式
String bucketName = qCloudCosConfig.getBucketName();
// 对象键(Key)是对象在存储桶中的唯一标识。详情请参见 [对象键](https://cloud.tencent.com/document/product/436/13324)
String key = qCloudCosConfig.getKeyName() + folder + objectKey;
String key = qCloudCosConfig.getKeyName() + filePath;
return cosClient.doesObjectExist(bucketName, key);
}

View File

@@ -261,7 +261,7 @@ public class ExportController extends BaseController {
return;
}
String[] headers = {""/*编号*/, "书名", "格式", "总页数", "语言", "是否有水印/广告", "扫描版/电子版", "文件大小", "来源信息 & 备注", "下载地址"}; // "作者", "出版社", "出版日期", "ISBN"
String[] headers = {""/*编号*/, "书名", "格式", "总页数", "语言", "是否有水印/广告", "扫描版/电子版", "文件大小", "来源", "下载地址"}; // "作者", "出版社", "出版日期", "ISBN"
MarkdownTable markdownTable = MarkdownTable.create()
.setHeader(headers)
.setAlignment(MarkdownTable.Alignment.LEFT)
@@ -298,17 +298,17 @@ public class ExportController extends BaseController {
strings[5] = String.join("", a);// 是否有水印/广告
// strings[6] = fileDO.getScan() ? "扫描版" : "电子版";// 扫描版/电子版
strings[7] = fileDO.getFileSize() + "";// 文件大小
strings[8] = fileDO.getBookOrigin() + "";// 来源信息 & 备注
strings[8] = fileDO.getSource() + "";// 来源信息 & 备注
List<String> url = new ArrayList<>();
StringBuilder download = new StringBuilder();
for (FileObjectNode fileObjectNode : fileNode.children) {
FileObjectDO fileObjectDO = fileObjectNode.current;
// 打印出当前书籍的文件对象信息
// System.out.println(getSpace(level - 1) + "\t\t\t[文件对象] " + fileObjectDO.getId() + "\t" + fileObjectDO.getFileName());
if (Objects.equals(fileObjectDO.getStorageMediumType(), FileStorageMediumEnum.QCLOUD_COS.getStorageMediumName()))
if (Objects.equals(fileObjectDO.getStorageMedium(), FileStorageMediumEnum.QCLOUD_COS.getStorageMediumName()))
continue;
download.append("[")
.append(FileStorageMediumEnum.valueOf(fileObjectDO.getStorageMediumType()).getStorageMediumDisplayName())
.append(FileStorageMediumEnum.valueOf(fileObjectDO.getStorageMedium()).getStorageMediumDisplayName())
.append("](")
.append(fileObjectDO.getFilePath())
.append(")");

View File

@@ -20,7 +20,6 @@ import plus.bookshelf.Config.QCloudCosConfig;
import plus.bookshelf.Controller.VO.FileObjectVO;
import plus.bookshelf.Controller.VO.FileVO;
import plus.bookshelf.Service.Impl.*;
import plus.bookshelf.Service.Model.FailureFeedbackModel;
import plus.bookshelf.Service.Model.FileModel;
import plus.bookshelf.Service.Model.FileObjectModel;
import plus.bookshelf.Service.Model.UserModel;
@@ -70,7 +69,7 @@ public class FileController extends BaseController {
List<FileObjectModel> fileObjectModels = fileObjectService.getFileObjectByBookId(bookId);
List<FileObjectVO> fileObjectVOS = new ArrayList<>();
for (FileObjectModel fileObjectModel : fileObjectModels) {
FileObjectVO fileObjectVO = convertFileObjectVOFromModel(fileObjectModel);
FileObjectVO fileObjectVO = FileObjectController.convertFileObjectVOFromModel(fileObjectModel);
fileObjectVOS.add(fileObjectVO);
}
@@ -101,10 +100,10 @@ public class FileController extends BaseController {
}
@ApiOperation(value = "【管理员】查询文件列表(匹配文件哈希)", notes = "查询文件列表,返回文件哈希为空或者相同的文件")
@RequestMapping(value = "list/MatchfileHash", method = {RequestMethod.POST}, consumes = {CONTENT_TYPE_FORMED})
@RequestMapping(value = "list/MatchfileHashWithNullValue", method = {RequestMethod.POST}, consumes = {CONTENT_TYPE_FORMED})
@ResponseBody
public CommonReturnType matchfileHash(@RequestParam(value = "token", required = false) String token,
@RequestParam(value = "fileSha1", required = true) String fileSha1) throws InvocationTargetException, IllegalAccessException, BusinessException {
public CommonReturnType matchfileHashWithNullValue(@RequestParam(value = "token", required = false) String token,
@RequestParam(value = "fileSha1", required = true) String fileSha1) throws InvocationTargetException, IllegalAccessException, BusinessException {
UserModel userModel = userService.getUserByToken(redisTemplate, token);
if (userModel == null || !Objects.equals(userModel.getGroup(), "ADMIN")) {
@@ -120,112 +119,20 @@ public class FileController extends BaseController {
return CommonReturnType.create(fileVOS);
}
@ApiOperation(value = "链接失效反馈", notes = "查询文件列表")
@RequestMapping(value = "object/FailureFeedback", method = {RequestMethod.POST}, consumes = {CONTENT_TYPE_FORMED})
@ApiOperation(value = "【管理员】通过文件SHA1哈希查找文件Id", notes = "查询文件列表返回文件哈希匹配的文件Id")
@RequestMapping(value = "getFileByHash", method = {RequestMethod.POST}, consumes = {CONTENT_TYPE_FORMED})
@ResponseBody
public CommonReturnType failureFeedback(@RequestParam(value = "token", required = false) String token,
@RequestParam(value = "bookId", required = false) Integer bookId,
@RequestParam(value = "fileId", required = false) Integer fileId,
@RequestParam(value = "fileObjectId", required = false) Integer fileObjectId,
@RequestParam(value = "visitorId", required = true) String visitorFingerprint) throws BusinessException {
Integer userId = null;
if (token != null) {
try {
UserModel userModel = userService.getUserByToken(redisTemplate, token);
userId = userModel.getId();
} catch (BusinessException e) {
// 用户未登录,不返回错误信息
}
}
if (!visitorFingerprintLogService.saveFingerprint("Failure Feedback", userId, visitorFingerprint)) {
throw new BusinessException(BusinessErrorCode.OPERATION_NOT_ALLOWED, "参数错误,请联系管理员处理");
}
FailureFeedbackModel failureFeedbackModel = new FailureFeedbackModel();
failureFeedbackModel.setBookId(bookId);
failureFeedbackModel.setFileId(fileId);
failureFeedbackModel.setFileObjectId(fileObjectId);
failureFeedbackModel.setUserId(userId);
failureFeedbackModel.setCreateTime(Calendar.getInstance().getTime());
Boolean isSuccess = failureFeedbackService.addFailureFeedback(failureFeedbackModel);
if (!isSuccess) {
throw new BusinessException(BusinessErrorCode.UNKNOWN_ERROR, "反馈失败");
}
return CommonReturnType.create(isSuccess);
}
@ApiOperation(value = "【管理员】查询文件对象列表", notes = "查询文件列表")
@RequestMapping(value = "object/list", method = {RequestMethod.POST}, consumes = {CONTENT_TYPE_FORMED})
@ResponseBody
public CommonReturnType objectList(@RequestParam(value = "token", required = false) String token) throws InvocationTargetException, IllegalAccessException, BusinessException {
public CommonReturnType getFileByHash(@RequestParam(value = "token", required = false) String token,
@RequestParam(value = "fileSha1", required = true) String fileSha1) throws InvocationTargetException, IllegalAccessException, BusinessException {
UserModel userModel = userService.getUserByToken(redisTemplate, token);
if (userModel == null || !Objects.equals(userModel.getGroup(), "ADMIN")) {
throw new BusinessException(BusinessErrorCode.OPERATION_NOT_ALLOWED, "非管理员用户无权进行此操作");
}
List<FileObjectModel> fileObjectModels = fileObjectService.list(token);
List<FileObjectVO> fileObjectVOS = new ArrayList<>();
for (FileObjectModel fileObjectModel : fileObjectModels) {
FileObjectVO fileObjectVO = convertFileObjectVOFromModel(fileObjectModel);
fileObjectVOS.add(fileObjectVO);
}
return CommonReturnType.create(fileObjectVOS);
}
@ApiOperation(value = "【管理员】更新文件对象上传状态", notes = "重新从 COS 对象存储中获取文件对象上传状态")
@RequestMapping(value = "object/refreshFileObjectStatus", method = {RequestMethod.POST}, consumes = {CONTENT_TYPE_FORMED})
@ResponseBody
public CommonReturnType refreshFileObjectStatus(@RequestParam(value = "token", required = false) String token,
@RequestParam(value = "fileObjectId") Integer fileObjectId) throws InvocationTargetException, IllegalAccessException, BusinessException {
// 验证用户权限
UserModel userModel = userService.getUserByToken(redisTemplate, token);
if (userModel == null || !Objects.equals(userModel.getGroup(), "ADMIN")) {
throw new BusinessException(BusinessErrorCode.OPERATION_NOT_ALLOWED, "非管理员用户无权进行此操作");
}
// 获取旧文件权限
FileObjectModel fileObjectModel = fileObjectService.getFileObjectById(fileObjectId);
String fileSha1 = fileObjectModel.getFileSha1();
String oldUploadStatus = fileObjectModel.getUploadStatus();
QCloudCosUtils qCloudCosUtils = new QCloudCosUtils(qCloudCosConfig, cosPresignedUrlGenerateLogService);
// 判断对象是否存在
Boolean isExist = qCloudCosUtils.doesObjectExist(QCloudCosUtils.BOOK_SAVE_FOLDER, fileSha1);
Boolean isSuccess = false;
if (!isExist) {
// 现在文件不存在
switch (oldUploadStatus) {
case "NOT_EXIST": // 文件不存在,不需要更新
default:
isSuccess = true;
break;
case "SUCCESS": // 上传成功,但是文件不存在了,更新为不存在
case "UPLOADING": // 上传中,更新为不存在
isSuccess = fileObjectService.updateFileStatus(fileObjectModel.getId(), "NOT_EXIST");
break;
}
} else {
// 现在文件存在
switch (oldUploadStatus) {
case "SUCCESS": // 之前上传成功,现在存在,不做任何操作
default:
isSuccess = true;
break;
case "NOT_EXIST": // 之前不存在,现在存在,更新为上传成功
case "UPLOADING": // 之前上传中,现在存在,更新为上传成功
isSuccess = fileObjectService.updateFileStatus(fileObjectModel.getId(), "SUCCESS");
break;
}
}
return CommonReturnType.create(isSuccess);
FileModel fileModel = fileService.selectBySha1(fileSha1);
FileVO fileVO = convertFileVOFromModel(fileModel);
return CommonReturnType.create(fileVO);
}
/**
@@ -291,13 +198,17 @@ public class FileController extends BaseController {
switch (httpMethodName) {
case PUT:
// 上传文件
if (isExist) throw new BusinessException(BusinessErrorCode.PARAMETER_VALIDATION_ERROR, "文件已存在");
if (isExist) throw new BusinessException(BusinessErrorCode.FILE_ALREADY_EXIST, "文件已存在");
Integer[] integers = fileObjectService.uploadFile(fileId, fileName, bookSaveFolder + fileSha1, fileSize,
fileSha1, fileExt, FileStorageMediumEnum.QCLOUD_COS, "", lastModified);
Integer realFileId = integers[0];
Integer fileObjectId = integers[1];
Integer realFileId = fileObjectService.uploadFile(fileId, fileName, bookSaveFolder + fileSha1, fileSize,
fileSha1, fileExt, fileName, FileStorageMediumEnum.QCLOUD_COS, "", lastModified);
// fileId 可能为 0 (创建新文件)
// realFileId 是从数据库中查询出来的真实的文件id
resultMap.put("fileId", realFileId);
resultMap.put("fileObjectId", fileObjectId);
url = qCloudCosUtils.generatePresignedUrl(userModel.getId(), httpMethodName, bookSaveFolder, fileSha1, expireMinute, urlGUID);
break;
case GET:
@@ -385,9 +296,10 @@ public class FileController extends BaseController {
if (fileObject == null) {
throw new BusinessException(BusinessErrorCode.PARAMETER_VALIDATION_ERROR, "文件不存在!");
}
// 更新文件状态
Boolean isSuccess = fileObjectService.updateFileStatus(fileObject.getId(), "SUCCESS");
if (!isSuccess) {
// 更新文件对象状态
Boolean isSuccess1 = fileObjectService.updateFileStatus(fileObject.getId(), "SUCCESS");
if (!isSuccess1) {
throw new BusinessException(BusinessErrorCode.UNKNOWN_ERROR, "更新文件状态失败");
}
} else {
@@ -407,20 +319,6 @@ public class FileController extends BaseController {
fileVO.setFileModifiedAt(fileModel.getFileModifiedAt().getTime());
return fileVO;
}
private FileObjectVO convertFileObjectVOFromModel(FileObjectModel fileObjectModel) {
if (fileObjectModel == null) {
return null;
}
FileObjectVO fileObjectVO = new FileObjectVO();
BeanUtils.copyProperties(fileObjectModel, fileObjectVO);
try {
// 尝试将 FileStorageMedium 转为中文,如果没有成功,那么就保留英文
fileObjectVO.setStorageMediumType(FileStorageMediumEnum.valueOf(fileObjectModel.getStorageMediumType()).getStorageMediumDisplayName());
} catch (Exception e) {
}
return fileObjectVO;
}
}
/*

View File

@@ -0,0 +1,180 @@
package plus.bookshelf.Controller.Controller;
import io.swagger.annotations.Api;
import io.swagger.annotations.ApiOperation;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Controller;
import org.springframework.web.bind.annotation.RequestMapping;
import org.springframework.web.bind.annotation.RequestMethod;
import org.springframework.web.bind.annotation.RequestParam;
import org.springframework.web.bind.annotation.ResponseBody;
import plus.bookshelf.Common.Enum.FileStorageMediumEnum;
import plus.bookshelf.Common.Error.BusinessErrorCode;
import plus.bookshelf.Common.Error.BusinessException;
import plus.bookshelf.Common.FileManager.QCloudCosUtils;
import plus.bookshelf.Common.Response.CommonReturnType;
import plus.bookshelf.Config.QCloudCosConfig;
import plus.bookshelf.Controller.VO.FileObjectVO;
import plus.bookshelf.Service.Impl.*;
import plus.bookshelf.Service.Model.FailureFeedbackModel;
import plus.bookshelf.Service.Model.FileModel;
import plus.bookshelf.Service.Model.FileObjectModel;
import plus.bookshelf.Service.Model.UserModel;
import plus.bookshelf.Service.Service.CosPresignedUrlGenerateLogService;
import java.lang.reflect.InvocationTargetException;
import java.util.ArrayList;
import java.util.Calendar;
import java.util.List;
import java.util.Objects;
@Api(tags = "文件对象管理")
@Controller("file/object")
@RequestMapping("/file/object")
public class FileObjectController extends BaseController {
@Autowired
QCloudCosConfig qCloudCosConfig;
@Autowired
UserServiceImpl userService;
@Autowired
FileServiceImpl fileService;
@Autowired
CosPresignedUrlGenerateLogService cosPresignedUrlGenerateLogService;
@Autowired
FileObjectServiceImpl fileObjectService;
@Autowired
FailureFeedbackServiceImpl failureFeedbackService;
@Autowired
VisitorFingerprintLogServiceImpl visitorFingerprintLogService;
@ApiOperation(value = "链接失效反馈", notes = "查询文件列表")
@RequestMapping(value = "FailureFeedback", method = {RequestMethod.POST}, consumes = {CONTENT_TYPE_FORMED})
@ResponseBody
public CommonReturnType failureFeedback(@RequestParam(value = "token", required = false) String token,
@RequestParam(value = "bookId", required = false) Integer bookId,
@RequestParam(value = "fileId", required = false) Integer fileId,
@RequestParam(value = "fileObjectId", required = false) Integer fileObjectId,
@RequestParam(value = "visitorId", required = true) String visitorFingerprint) throws BusinessException {
Integer userId = null;
if (token != null) {
try {
UserModel userModel = userService.getUserByToken(redisTemplate, token);
userId = userModel.getId();
} catch (BusinessException e) {
// 用户未登录,不返回错误信息
}
}
if (!visitorFingerprintLogService.saveFingerprint("Failure Feedback", userId, visitorFingerprint)) {
throw new BusinessException(BusinessErrorCode.OPERATION_NOT_ALLOWED, "参数错误,请联系管理员处理");
}
FailureFeedbackModel failureFeedbackModel = new FailureFeedbackModel();
failureFeedbackModel.setBookId(bookId);
failureFeedbackModel.setFileId(fileId);
failureFeedbackModel.setFileObjectId(fileObjectId);
failureFeedbackModel.setUserId(userId);
failureFeedbackModel.setCreateTime(Calendar.getInstance().getTime());
Boolean isSuccess = failureFeedbackService.addFailureFeedback(failureFeedbackModel);
if (!isSuccess) {
throw new BusinessException(BusinessErrorCode.UNKNOWN_ERROR, "反馈失败");
}
return CommonReturnType.create(isSuccess);
}
@ApiOperation(value = "【管理员】查询文件对象列表", notes = "查询文件列表")
@RequestMapping(value = "list", method = {RequestMethod.POST}, consumes = {CONTENT_TYPE_FORMED})
@ResponseBody
public CommonReturnType objectList(@RequestParam(value = "token", required = false) String token) throws InvocationTargetException, IllegalAccessException, BusinessException {
UserModel userModel = userService.getUserByToken(redisTemplate, token);
if (userModel == null || !Objects.equals(userModel.getGroup(), "ADMIN")) {
throw new BusinessException(BusinessErrorCode.OPERATION_NOT_ALLOWED, "非管理员用户无权进行此操作");
}
List<FileObjectModel> fileObjectModels = fileObjectService.list();
List<FileObjectVO> fileObjectVOS = new ArrayList<>();
for (FileObjectModel fileObjectModel : fileObjectModels) {
FileObjectVO fileObjectVO = convertFileObjectVOFromModel(fileObjectModel);
fileObjectVOS.add(fileObjectVO);
}
return CommonReturnType.create(fileObjectVOS);
}
@ApiOperation(value = "【管理员】更新文件对象上传状态", notes = "重新从 COS 对象存储中获取文件对象上传状态")
@RequestMapping(value = "refreshFileObjectStatus", method = {RequestMethod.POST}, consumes = {CONTENT_TYPE_FORMED})
@ResponseBody
public CommonReturnType refreshFileObjectStatus(@RequestParam(value = "token", required = false) String token,
@RequestParam(value = "fileObjectId") Integer fileObjectId) throws InvocationTargetException, IllegalAccessException, BusinessException {
// 验证用户权限
UserModel userModel = userService.getUserByToken(redisTemplate, token);
if (userModel == null || !Objects.equals(userModel.getGroup(), "ADMIN")) {
throw new BusinessException(BusinessErrorCode.OPERATION_NOT_ALLOWED, "非管理员用户无权进行此操作");
}
// 获取旧文件权限
FileObjectModel fileObjectModel = fileObjectService.getFileObjectById(fileObjectId);
String filePath = fileObjectModel.getFilePath();
String oldUploadStatus = fileObjectModel.getUploadStatus();
QCloudCosUtils qCloudCosUtils = new QCloudCosUtils(qCloudCosConfig, cosPresignedUrlGenerateLogService);
// 判断对象是否存在
Boolean isExist = qCloudCosUtils.doesObjectExist(filePath);
Boolean isSuccess = false;
if (!isExist) {
// 现在文件不存在
switch (oldUploadStatus) {
case "NOT_EXIST": // 文件不存在,不需要更新
default:
isSuccess = true;
break;
case "SUCCESS": // 上传成功,但是文件不存在了,更新为不存在
case "UPLOADING": // 上传中,更新为不存在
isSuccess = fileObjectService.updateFileStatus(fileObjectModel.getId(), "NOT_EXIST");
break;
}
} else {
// 现在文件存在
switch (oldUploadStatus) {
case "SUCCESS": // 之前上传成功,现在存在,不做任何操作
default:
isSuccess = true;
break;
case "NOT_EXIST": // 之前不存在,现在存在,更新为上传成功
case "UPLOADING": // 之前上传中,现在存在,更新为上传成功
isSuccess = fileObjectService.updateFileStatus(fileObjectModel.getId(), "SUCCESS");
break;
}
}
return CommonReturnType.create(isSuccess);
}
public static FileObjectVO convertFileObjectVOFromModel(FileObjectModel fileObjectModel) {
if (fileObjectModel == null) {
return null;
}
FileObjectVO fileObjectVO = new FileObjectVO();
BeanUtils.copyProperties(fileObjectModel, fileObjectVO);
try {
// 尝试将 FileStorageMedium 转为中文,如果没有成功,那么就保留英文
fileObjectVO.setStorageMedium(FileStorageMediumEnum.valueOf(fileObjectModel.getStorageMedium()).getStorageMediumDisplayName());
} catch (Exception e) {
}
return fileObjectVO;
}
}

View File

@@ -11,17 +11,11 @@ public class FileObjectVO {
// 存储的文件Id
private Integer fileId;
// 文件
private String fileName;
// 文件大小
private Long fileSize;
// 文件类型
private String fileType;
// 文件上传状态
String uploadStatus;
// 文件存储介质类型
String storageMediumType;
String storageMedium;
// 文件地址
// 如果是网盘就是分享链接,如果是本地存储就是文件路径
@@ -35,13 +29,4 @@ public class FileObjectVO {
// 文件最后修改时间戳
Long lastModified;
// 文件上传状态
String uploadStatus;
// 文件哈希 - SHA1
String fileSha1;
// 附加字段(JSON存储)
String additionalFields;
}

View File

@@ -11,14 +11,17 @@ public class FileVO {
// 关联的书籍Id
Integer bookId;
// 文件名 (用于展示给用户的文件名,不含扩展名)
String fileDisplayName;
// 文件存储名称 (文件的实际文件名,含扩展名)
// 文件名,不含扩展名
String fileName;
// 文件格式
String fileFormat;
// 文件扩展名
String fileExt;
// 文件大小
long fileSize;
// 文件哈希 - SHA1
String fileSha1;
// 总页数
Integer numberOfPages;
@@ -30,17 +33,11 @@ public class FileVO {
Boolean advertising;
// 文件来源 电子版/扫描版
String bookOrigin;
String source;
// 文件创建时间
long fileCreateAt;
// 文件修改时间
long fileModifiedAt;
// 文件大小
long fileSize;
// 文件哈希 - SHA1
String fileSha1;
}

View File

@@ -21,15 +21,6 @@ public class FileDO {
*/
private Integer bookId;
/**
*
* This field was generated by MyBatis Generator.
* This field corresponds to the database column file_info.file_display_name
*
* @mbg.generated
*/
private String fileDisplayName;
/**
*
* This field was generated by MyBatis Generator.
@@ -42,11 +33,29 @@ public class FileDO {
/**
*
* This field was generated by MyBatis Generator.
* This field corresponds to the database column file_info.file_format
* This field corresponds to the database column file_info.file_ext
*
* @mbg.generated
*/
private String fileFormat;
private String fileExt;
/**
*
* This field was generated by MyBatis Generator.
* This field corresponds to the database column file_info.file_size
*
* @mbg.generated
*/
private Long fileSize;
/**
*
* This field was generated by MyBatis Generator.
* This field corresponds to the database column file_info.file_sha1
*
* @mbg.generated
*/
private String fileSha1;
/**
*
@@ -78,11 +87,11 @@ public class FileDO {
/**
*
* This field was generated by MyBatis Generator.
* This field corresponds to the database column file_info.book_origin
* This field corresponds to the database column file_info.source
*
* @mbg.generated
*/
private String bookOrigin;
private String source;
/**
*
@@ -102,24 +111,6 @@ public class FileDO {
*/
private Date fileModifiedAt;
/**
*
* This field was generated by MyBatis Generator.
* This field corresponds to the database column file_info.file_size
*
* @mbg.generated
*/
private Long fileSize;
/**
*
* This field was generated by MyBatis Generator.
* This field corresponds to the database column file_info.file_sha1
*
* @mbg.generated
*/
private String fileSha1;
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column file_info.id
@@ -168,30 +159,6 @@ public class FileDO {
this.bookId = bookId;
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column file_info.file_display_name
*
* @return the value of file_info.file_display_name
*
* @mbg.generated
*/
public String getFileDisplayName() {
return fileDisplayName;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column file_info.file_display_name
*
* @param fileDisplayName the value for file_info.file_display_name
*
* @mbg.generated
*/
public void setFileDisplayName(String fileDisplayName) {
this.fileDisplayName = fileDisplayName == null ? null : fileDisplayName.trim();
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column file_info.file_name
@@ -218,26 +185,74 @@ public class FileDO {
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column file_info.file_format
* This method returns the value of the database column file_info.file_ext
*
* @return the value of file_info.file_format
* @return the value of file_info.file_ext
*
* @mbg.generated
*/
public String getFileFormat() {
return fileFormat;
public String getFileExt() {
return fileExt;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column file_info.file_format
* This method sets the value of the database column file_info.file_ext
*
* @param fileFormat the value for file_info.file_format
* @param fileExt the value for file_info.file_ext
*
* @mbg.generated
*/
public void setFileFormat(String fileFormat) {
this.fileFormat = fileFormat == null ? null : fileFormat.trim();
public void setFileExt(String fileExt) {
this.fileExt = fileExt == null ? null : fileExt.trim();
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column file_info.file_size
*
* @return the value of file_info.file_size
*
* @mbg.generated
*/
public Long getFileSize() {
return fileSize;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column file_info.file_size
*
* @param fileSize the value for file_info.file_size
*
* @mbg.generated
*/
public void setFileSize(Long fileSize) {
this.fileSize = fileSize;
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column file_info.file_sha1
*
* @return the value of file_info.file_sha1
*
* @mbg.generated
*/
public String getFileSha1() {
return fileSha1;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column file_info.file_sha1
*
* @param fileSha1 the value for file_info.file_sha1
*
* @mbg.generated
*/
public void setFileSha1(String fileSha1) {
this.fileSha1 = fileSha1 == null ? null : fileSha1.trim();
}
/**
@@ -314,26 +329,26 @@ public class FileDO {
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column file_info.book_origin
* This method returns the value of the database column file_info.source
*
* @return the value of file_info.book_origin
* @return the value of file_info.source
*
* @mbg.generated
*/
public String getBookOrigin() {
return bookOrigin;
public String getSource() {
return source;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column file_info.book_origin
* This method sets the value of the database column file_info.source
*
* @param bookOrigin the value for file_info.book_origin
* @param source the value for file_info.source
*
* @mbg.generated
*/
public void setBookOrigin(String bookOrigin) {
this.bookOrigin = bookOrigin == null ? null : bookOrigin.trim();
public void setSource(String source) {
this.source = source == null ? null : source.trim();
}
/**
@@ -383,52 +398,4 @@ public class FileDO {
public void setFileModifiedAt(Date fileModifiedAt) {
this.fileModifiedAt = fileModifiedAt;
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column file_info.file_size
*
* @return the value of file_info.file_size
*
* @mbg.generated
*/
public Long getFileSize() {
return fileSize;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column file_info.file_size
*
* @param fileSize the value for file_info.file_size
*
* @mbg.generated
*/
public void setFileSize(Long fileSize) {
this.fileSize = fileSize;
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column file_info.file_sha1
*
* @return the value of file_info.file_sha1
*
* @mbg.generated
*/
public String getFileSha1() {
return fileSha1;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column file_info.file_sha1
*
* @param fileSha1 the value for file_info.file_sha1
*
* @mbg.generated
*/
public void setFileSha1(String fileSha1) {
this.fileSha1 = fileSha1 == null ? null : fileSha1.trim();
}
}

View File

@@ -22,38 +22,20 @@ public class FileObjectDO {
/**
*
* This field was generated by MyBatis Generator.
* This field corresponds to the database column file_object_info.file_name
* This field corresponds to the database column file_object_info.upload_status
*
* @mbg.generated
*/
private String fileName;
private String uploadStatus;
/**
*
* This field was generated by MyBatis Generator.
* This field corresponds to the database column file_object_info.file_size
* This field corresponds to the database column file_object_info.storage_medium
*
* @mbg.generated
*/
private Long fileSize;
/**
*
* This field was generated by MyBatis Generator.
* This field corresponds to the database column file_object_info.file_type
*
* @mbg.generated
*/
private String fileType;
/**
*
* This field was generated by MyBatis Generator.
* This field corresponds to the database column file_object_info.storage_medium_type
*
* @mbg.generated
*/
private String storageMediumType;
private String storageMedium;
/**
*
@@ -82,24 +64,6 @@ public class FileObjectDO {
*/
private String fileShareCode;
/**
*
* This field was generated by MyBatis Generator.
* This field corresponds to the database column file_object_info.upload_status
*
* @mbg.generated
*/
private String uploadStatus;
/**
*
* This field was generated by MyBatis Generator.
* This field corresponds to the database column file_object_info.file_sha1
*
* @mbg.generated
*/
private String fileSha1;
/**
*
* This field was generated by MyBatis Generator.
@@ -109,15 +73,6 @@ public class FileObjectDO {
*/
private Long lastModified;
/**
*
* This field was generated by MyBatis Generator.
* This field corresponds to the database column file_object_info.additional_fields
*
* @mbg.generated
*/
private String additionalFields;
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column file_object_info.id
@@ -168,98 +123,50 @@ public class FileObjectDO {
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column file_object_info.file_name
* This method returns the value of the database column file_object_info.upload_status
*
* @return the value of file_object_info.file_name
* @return the value of file_object_info.upload_status
*
* @mbg.generated
*/
public String getFileName() {
return fileName;
public String getUploadStatus() {
return uploadStatus;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column file_object_info.file_name
* This method sets the value of the database column file_object_info.upload_status
*
* @param fileName the value for file_object_info.file_name
* @param uploadStatus the value for file_object_info.upload_status
*
* @mbg.generated
*/
public void setFileName(String fileName) {
this.fileName = fileName == null ? null : fileName.trim();
public void setUploadStatus(String uploadStatus) {
this.uploadStatus = uploadStatus == null ? null : uploadStatus.trim();
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column file_object_info.file_size
* This method returns the value of the database column file_object_info.storage_medium
*
* @return the value of file_object_info.file_size
* @return the value of file_object_info.storage_medium
*
* @mbg.generated
*/
public Long getFileSize() {
return fileSize;
public String getStorageMedium() {
return storageMedium;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column file_object_info.file_size
* This method sets the value of the database column file_object_info.storage_medium
*
* @param fileSize the value for file_object_info.file_size
* @param storageMedium the value for file_object_info.storage_medium
*
* @mbg.generated
*/
public void setFileSize(Long fileSize) {
this.fileSize = fileSize;
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column file_object_info.file_type
*
* @return the value of file_object_info.file_type
*
* @mbg.generated
*/
public String getFileType() {
return fileType;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column file_object_info.file_type
*
* @param fileType the value for file_object_info.file_type
*
* @mbg.generated
*/
public void setFileType(String fileType) {
this.fileType = fileType == null ? null : fileType.trim();
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column file_object_info.storage_medium_type
*
* @return the value of file_object_info.storage_medium_type
*
* @mbg.generated
*/
public String getStorageMediumType() {
return storageMediumType;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column file_object_info.storage_medium_type
*
* @param storageMediumType the value for file_object_info.storage_medium_type
*
* @mbg.generated
*/
public void setStorageMediumType(String storageMediumType) {
this.storageMediumType = storageMediumType == null ? null : storageMediumType.trim();
public void setStorageMedium(String storageMedium) {
this.storageMedium = storageMedium == null ? null : storageMedium.trim();
}
/**
@@ -334,54 +241,6 @@ public class FileObjectDO {
this.fileShareCode = fileShareCode == null ? null : fileShareCode.trim();
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column file_object_info.upload_status
*
* @return the value of file_object_info.upload_status
*
* @mbg.generated
*/
public String getUploadStatus() {
return uploadStatus;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column file_object_info.upload_status
*
* @param uploadStatus the value for file_object_info.upload_status
*
* @mbg.generated
*/
public void setUploadStatus(String uploadStatus) {
this.uploadStatus = uploadStatus == null ? null : uploadStatus.trim();
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column file_object_info.file_sha1
*
* @return the value of file_object_info.file_sha1
*
* @mbg.generated
*/
public String getFileSha1() {
return fileSha1;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column file_object_info.file_sha1
*
* @param fileSha1 the value for file_object_info.file_sha1
*
* @mbg.generated
*/
public void setFileSha1(String fileSha1) {
this.fileSha1 = fileSha1 == null ? null : fileSha1.trim();
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column file_object_info.last_modified
@@ -405,28 +264,4 @@ public class FileObjectDO {
public void setLastModified(Long lastModified) {
this.lastModified = lastModified;
}
/**
* This method was generated by MyBatis Generator.
* This method returns the value of the database column file_object_info.additional_fields
*
* @return the value of file_object_info.additional_fields
*
* @mbg.generated
*/
public String getAdditionalFields() {
return additionalFields;
}
/**
* This method was generated by MyBatis Generator.
* This method sets the value of the database column file_object_info.additional_fields
*
* @param additionalFields the value for file_object_info.additional_fields
*
* @mbg.generated
*/
public void setAdditionalFields(String additionalFields) {
this.additionalFields = additionalFields == null ? null : additionalFields.trim();
}
}

View File

@@ -61,12 +61,19 @@ public interface FileDOMapper {
FileDO[] selectAll();
/**
* 查询系统中所有文件
* 查询系统中所有 SHA1匹配 和 未设置SHA1 的文件
*
* @return
*/
FileDO[] selectBySha1WithNullValue(String fileSha1);
/**
* 查询系统中一个 SHA1匹配 的文件
*
* @return
*/
FileDO selectBySha1(String fileSha1);
/**
* 列出文件支持的下载方式
*
@@ -87,4 +94,13 @@ public interface FileDOMapper {
* @return
*/
int getLastInsertId();
/**
* 更新文件的SHA1值
*
* @param id 文件Id
* @param fileSha1 文件的SHA1值
* @return
*/
int updateFileSha1(Integer id, String fileSha1);
}

View File

@@ -75,4 +75,11 @@ public interface FileObjectDOMapper {
* @return
*/
FileObjectDO[] selectFileObjectByBookId(Integer bookId);
/**
* 获取上一次插入的主键Id
*
* @return
*/
int getLastInsertId();
}

View File

@@ -12,7 +12,6 @@ import plus.bookshelf.Dao.DO.FileObjectDO;
import plus.bookshelf.Dao.Mapper.FileObjectDOMapper;
import plus.bookshelf.Service.Model.FileModel;
import plus.bookshelf.Service.Model.FileObjectModel;
import plus.bookshelf.Service.Model.UserModel;
import plus.bookshelf.Service.Service.FileObjectService;
import java.lang.reflect.InvocationTargetException;
@@ -61,10 +60,7 @@ public class FileObjectServiceImpl implements FileObjectService {
* @return
*/
@Override
public List<FileObjectModel> list(String token) throws InvocationTargetException, IllegalAccessException, BusinessException {
// 已经在 getUserByToken 方法中判断了 token 为空、不合法;用户不存在情况,此处无需再判断
UserModel userModel = userService.getUserByToken(redisTemplate, token);
public List<FileObjectModel> list() throws InvocationTargetException, IllegalAccessException, BusinessException {
FileObjectDO[] fileObjectDOS = fileObjectDOMapper.selectAll();
@@ -120,9 +116,9 @@ public class FileObjectServiceImpl implements FileObjectService {
* @param fileSize 文件大小
* @param fileSHA1 文件SHA1
* @param fileExt 文件扩展名
* @param fileNameWithoutExt 文件名(不包含扩展名)
* @param fileName 文件名(不包含扩展名)
* @param fileStorageMediumEnum 文件存储介质
* @param bookOrigin 文件来源
* @param source 文件来源
* @return 返回文件Id
* @throws InvocationTargetException
* @throws IllegalAccessException
@@ -130,9 +126,9 @@ public class FileObjectServiceImpl implements FileObjectService {
*/
@Override
@Transactional
public Integer uploadFile(Integer fileId, String fileName, String filePath, Long fileSize, String fileSHA1,
String fileExt, String fileNameWithoutExt, FileStorageMediumEnum fileStorageMediumEnum,
String bookOrigin, Long lastModified
public Integer[] uploadFile(Integer fileId, String fileName, String filePath, Long fileSize, String fileSHA1,
String fileExt, FileStorageMediumEnum fileStorageMediumEnum,
String source, Long lastModified
) throws InvocationTargetException, IllegalAccessException, BusinessException {
if (fileId == 0) {
@@ -142,9 +138,8 @@ public class FileObjectServiceImpl implements FileObjectService {
fileModel.setFileName(fileName);
fileModel.setFileSize(fileSize);
fileModel.setFileSha1(fileSHA1);
fileModel.setFileFormat(fileExt);
fileModel.setFileDisplayName(fileNameWithoutExt);
fileModel.setBookOrigin(bookOrigin);
fileModel.setFileExt(fileExt);
fileModel.setSource(source);
// 其余使用默认设置
fileModel.setBookId(0);
@@ -171,25 +166,24 @@ public class FileObjectServiceImpl implements FileObjectService {
fileObjectModel.setFileId(fileId);
fileObjectModel.setFileName(fileName);
fileObjectModel.setFileSize(fileSize);
fileObjectModel.setFileType(fileExt);
fileObjectModel.setStorageMediumType(fileStorageMediumEnum.getStorageMediumName());
fileObjectModel.setStorageMedium(fileStorageMediumEnum.getStorageMediumName());
fileObjectModel.setFilePath(filePath);
fileObjectModel.setFileSha1(fileSHA1);
fileObjectModel.setUploadStatus("UPLOADING");
fileObjectModel.setLastModified(lastModified);
// 其余使用默认设置
fileObjectModel.setFilePwd("");
fileObjectModel.setFileShareCode("");
fileObjectModel.setAdditionalFields("");
Boolean isSuccess = addFileObject(fileObjectModel);
if (!isSuccess) {
throw new BusinessException(BusinessErrorCode.UNKNOWN_ERROR, "文件对象创建失败");
}
return fileId;
int lastInsertId = fileObjectDOMapper.getLastInsertId();
// fileId, fileObjectId
return new Integer[]{fileId, lastInsertId};
}
/**
@@ -199,7 +193,7 @@ public class FileObjectServiceImpl implements FileObjectService {
* @param fileStatus
*/
@Override
public Boolean updateFileStatus(Integer fileObjectId, String fileStatus) throws InvocationTargetException, IllegalAccessException {
public Boolean updateFileStatus(Integer fileObjectId, String fileStatus) {
if (fileObjectId == null || fileObjectId == 0) {
return false;
}

View File

@@ -100,6 +100,18 @@ public class FileServiceImpl implements FileService {
return fileModels;
}
/**
* 列出一个 SHA1匹配 的文件
*
* @return
*/
@Override
public FileModel selectBySha1(String fileSha1) {
FileDO fileDO = fileDOMapper.selectBySha1(fileSha1);
FileModel fileModel = convertFromDataObject(fileDO);
return fileModel;
}
private FileModel convertFromDataObject(FileDO fileDO) {
if (fileDO == null) {
return null;
@@ -119,13 +131,13 @@ public class FileServiceImpl implements FileService {
* @throws IllegalAccessException
*/
@Override
public Boolean addFile(FileModel fileModel) throws InvocationTargetException, IllegalAccessException {
FileDO fileDO = copyFileToDataObject(fileModel);
public Boolean addFile(FileModel fileModel) {
FileDO fileDO = convertFromFileModel(fileModel);
int affectRows = fileDOMapper.insertSelective(fileDO);
return affectRows > 0;
}
private FileDO copyFileToDataObject(FileModel fileModel) throws InvocationTargetException, IllegalAccessException {
private FileDO convertFromFileModel(FileModel fileModel) {
FileDO fileDO = new FileDO();
BeanUtils.copyProperties(fileModel, fileDO);
return fileDO;
@@ -150,4 +162,31 @@ public class FileServiceImpl implements FileService {
public Integer getLastInsertId() {
return fileDOMapper.getLastInsertId();
}
/**
* 更新文件的SHA1值
*
* @return
*/
@Override
public Boolean updateFileSha1(Integer fileId, String fileSha1) throws BusinessException {
if (fileId == null || fileId == 0) {
throw new BusinessException(BusinessErrorCode.PARAMETER_VALIDATION_ERROR, "fileId不能为空");
}
Integer affectRows = fileDOMapper.updateFileSha1(fileId, fileSha1);
return affectRows > 0;
}
/**
* 通过文件对象Id找到文件Id
*
* @param fileObjectId
* @return
*/
@Override
public FileModel getFileByFileObjectId(Integer fileObjectId) {
FileDO fileDO = fileDOMapper.selectByPrimaryKey(fileObjectId);
FileModel fileModel = convertFromDataObject(fileDO);
return fileModel;
}
}

View File

@@ -1,146 +0,0 @@
package plus.bookshelf.Service.Impl;
import org.springframework.beans.BeanUtils;
import org.springframework.beans.factory.annotation.Autowired;
import org.springframework.stereotype.Service;
import org.springframework.transaction.annotation.Transactional;
import plus.bookshelf.Common.Enum.ScheduleTaskActionEnum;
import plus.bookshelf.Common.Error.BusinessErrorCode;
import plus.bookshelf.Common.Error.BusinessException;
import plus.bookshelf.Common.FileManager.QCloudCosUtils;
import plus.bookshelf.Config.QCloudCosConfig;
import plus.bookshelf.Dao.DO.ScheduleTaskDO;
import plus.bookshelf.Dao.Mapper.ScheduleTaskDOMapper;
import plus.bookshelf.Service.Model.ScheduleTaskModel;
import plus.bookshelf.Service.Service.CosPresignedUrlGenerateLogService;
import java.util.Date;
import java.util.concurrent.Executors;
import java.util.concurrent.TimeUnit;
import static plus.bookshelf.Common.Enum.ScheduleTaskActionEnum.*;
@Service
public class ScheduleTaskServiceImpl {
@Autowired
QCloudCosConfig qCloudCosConfig;
@Autowired
CosPresignedUrlGenerateLogService cosPresignedUrlGenerateLogService;
@Autowired
ScheduleTaskDOMapper scheduleTaskDOMapper;
@Autowired
FileServiceImpl fileService;
public void setExecutor() {
// 创建定时任务 主要是待用户将文件上传成功到COS后
java.util.concurrent.ScheduledExecutorService service = Executors.newSingleThreadScheduledExecutor();
// 参数1、任务体 2、首次执行的延时时间
// 3、任务执行间隔 4、间隔时间单位
service.scheduleAtFixedRate(() -> {
try {
thingsTodo();
} catch (BusinessException e) {
e.printStackTrace();
}
}, 0, 3, TimeUnit.SECONDS);
}
@Transactional
public void thingsTodo() throws BusinessException {
// 检查上传文件后未收到客户端发来的上传完成消息的情况。
// 如果系统里面没有记录那么删除COS存储桶中用户上传的这个文件。
System.out.println("检查定时任务");
ScheduleTaskDO[] scheduleTaskDO = scheduleTaskDOMapper.selectTodoTask();
for (ScheduleTaskDO task : scheduleTaskDO) {
ScheduleTaskModel scheduleTaskModel = convertToModel(task);
switch (scheduleTaskModel.getAction()) {
case CHECK_FILE_IS_UPLOADED:
// TODO 系统中没有这个文件,而对象存储中有这个文件,那么删除对象存储中的文件
// fileService.doScheduleTask(scheduleTaskModel);
// 检查文件是否被上传
QCloudCosUtils qCloudCosUtils = new QCloudCosUtils(qCloudCosConfig, cosPresignedUrlGenerateLogService);
Boolean isExists = qCloudCosUtils.doesObjectExist(QCloudCosUtils.BOOK_SAVE_FOLDER, task.getData());
if (isExists) {
// 如果文件存在,则更新数据库中的状态
// TODO
System.out.println("文件已经上传,更新数据库中的状态");
}
// 在数据库中设置为完成
Boolean isDoneSuccess = doneScheduleTask(task.getId());
if (!isDoneSuccess) {
throw new BusinessException(BusinessErrorCode.UNKNOWN_ERROR, "系统错误!更新数据库中的状态失败");
}
break;
default:
throw new BusinessException(BusinessErrorCode.UNKNOWN_ERROR, "未知的定时任务类型");
}
}
// 输出
System.out.println("Task ScheduledExecutorService " + new Date());
}
/**
* 创建一个新的定时任务(存入数据库)
*
* @param scheduleTaskModel
* @return
*/
public Boolean insertScheduleTask(ScheduleTaskModel scheduleTaskModel) {
ScheduleTaskDO scheduleTaskDO = convertToDataObject(scheduleTaskModel);
int affectRows = scheduleTaskDOMapper.insertSelective(scheduleTaskDO);
return affectRows > 0;
}
/**
* 完成一个定时任务(从数据库中删除)
* 注意先删除,删除成功后才进行处理,避免自动触发和手动触发同时进行
*
* @param scheduleTaskId
* @return
*/
public Boolean doneScheduleTask(Integer scheduleTaskId) {
int affectRows = scheduleTaskDOMapper.deleteByPrimaryKey(scheduleTaskId);
return affectRows > 0;
}
/**
* 通过 Guid 查询任务
*
* @param guid
* @return
*/
public ScheduleTaskModel findTaskByGuid(String guid) {
ScheduleTaskDO scheduleTaskDO = scheduleTaskDOMapper.selectByGuid(guid);
return convertToModel(scheduleTaskDO);
}
private static ScheduleTaskDO convertToDataObject(ScheduleTaskModel scheduleTaskModel) {
if (scheduleTaskModel == null) {
return null;
}
ScheduleTaskDO scheduleTaskDO = new ScheduleTaskDO();
BeanUtils.copyProperties(scheduleTaskModel, scheduleTaskDO);
scheduleTaskDO.setAction(String.valueOf(scheduleTaskModel.getAction()));
return scheduleTaskDO;
}
private static ScheduleTaskModel convertToModel(ScheduleTaskDO scheduleTaskDO) {
if (scheduleTaskDO == null) {
return null;
}
ScheduleTaskModel scheduleTaskModel = new ScheduleTaskModel();
BeanUtils.copyProperties(scheduleTaskDO, scheduleTaskModel);
scheduleTaskModel.setAction(ScheduleTaskActionEnum.valueOf(scheduleTaskDO.getAction()));
return scheduleTaskModel;
}
}

View File

@@ -13,14 +13,17 @@ public class FileModel {
// 关联的书籍Id
Integer bookId;
// 文件名 (用于展示给用户的文件名,不含扩展名)
String fileDisplayName;
// 文件存储名称 (文件的实际文件名,含扩展名)
// 文件名,不含扩展名
String fileName;
// 文件格式 (文件扩展名)
String fileFormat;
// 文件扩展名
String fileExt;
// 文件大小
long fileSize;
// 文件哈希 - SHA1
String fileSha1;
// 总页数
Integer numberOfPages;
@@ -32,17 +35,11 @@ public class FileModel {
Boolean advertising;
// 文件来源 电子版/扫描版
String bookOrigin;
String source;
// 文件创建时间
Date fileCreateAt;
// 文件修改时间
Date fileModifiedAt;
// 文件大小
long fileSize;
// 文件哈希 - SHA1
String fileSha1;
}

View File

@@ -11,17 +11,11 @@ public class FileObjectModel {
// 存储的文件Id
private Integer fileId;
// 文件
private String fileName;
// 文件大小
private Long fileSize;
// 文件类型
private String fileType;
// 文件上传状态
String uploadStatus;
// 文件存储介质类型
String storageMediumType;
String storageMedium;
// 文件地址
// 如果是网盘就是分享链接,如果是本地存储就是文件路径
@@ -35,13 +29,4 @@ public class FileObjectModel {
// 文件最后修改时间戳
Long lastModified;
// 文件上传状态
String uploadStatus;
// 文件哈希 - SHA1
String fileSha1;
// 附加字段(JSON存储)
String additionalFields;
}

View File

@@ -25,7 +25,7 @@ public interface FileObjectService {
*
* @return
*/
List<FileObjectModel> list(String token) throws InvocationTargetException, IllegalAccessException, BusinessException;
List<FileObjectModel> list() throws InvocationTargetException, IllegalAccessException, BusinessException;
/**
* 添加文件对象
@@ -46,16 +46,16 @@ public interface FileObjectService {
* @param fileSize 文件大小
* @param fileSHA1 文件SHA1
* @param fileExt 文件扩展名
* @param fileNameWithoutExt 文件名(不包含扩展名)
* @param fileName 文件名(不包含扩展名)
* @param fileStorageMediumEnum 文件存储介质
* @param bookOrigin 文件来源
* @param source 文件来源
* @return 是否插入成功
* @throws InvocationTargetException
* @throws IllegalAccessException
* @throws BusinessException
*/
@Transactional
Integer uploadFile(Integer fileId, String fileName, String filePath, Long fileSize, String fileSHA1, String fileExt, String fileNameWithoutExt, FileStorageMediumEnum fileStorageMediumEnum, String bookOrigin, Long lastModified) throws InvocationTargetException, IllegalAccessException, BusinessException;
Integer[] uploadFile(Integer fileId, String fileName, String filePath, Long fileSize, String fileSHA1, String fileExt, FileStorageMediumEnum fileStorageMediumEnum, String source, Long lastModified) throws InvocationTargetException, IllegalAccessException, BusinessException;
/**
* 修改文件对象上传状态信息

View File

@@ -32,6 +32,14 @@ public interface FileService {
*/
List<FileModel> selectBySha1WithNullValue(String token) throws InvocationTargetException, IllegalAccessException, BusinessException;
/**
* 列出一个 SHA1匹配 的文件
*
* @param fileSha1
* @return
*/
FileModel selectBySha1(String fileSha1);
/**
* 添加文件信息
* 返回是否添加成功
@@ -56,4 +64,22 @@ public interface FileService {
* @return
*/
Integer getLastInsertId();
/**
* 更新文件的SHA1值
*
* @param fileId 文件Id
* @param fileSha1 文件SHA1值
* @return
* @throws BusinessException
*/
Boolean updateFileSha1(Integer fileId, String fileSha1) throws BusinessException;
/**
* 通过文件对象Id找到文件Id
*
* @param fileObjectId
* @return
*/
FileModel getFileByFileObjectId(Integer fileObjectId);
}

View File

@@ -8,25 +8,24 @@
-->
<id column="id" jdbcType="INTEGER" property="id" />
<result column="book_id" jdbcType="INTEGER" property="bookId" />
<result column="file_display_name" jdbcType="VARCHAR" property="fileDisplayName" />
<result column="file_name" jdbcType="VARCHAR" property="fileName" />
<result column="file_format" jdbcType="VARCHAR" property="fileFormat" />
<result column="file_ext" jdbcType="VARCHAR" property="fileExt" />
<result column="file_size" jdbcType="BIGINT" property="fileSize" />
<result column="file_sha1" jdbcType="VARCHAR" property="fileSha1" />
<result column="number_of_pages" jdbcType="INTEGER" property="numberOfPages" />
<result column="watermark" jdbcType="BIT" property="watermark" />
<result column="advertising" jdbcType="BIT" property="advertising" />
<result column="book_origin" jdbcType="VARCHAR" property="bookOrigin" />
<result column="source" jdbcType="VARCHAR" property="source" />
<result column="file_create_at" jdbcType="TIMESTAMP" property="fileCreateAt" />
<result column="file_modified_at" jdbcType="TIMESTAMP" property="fileModifiedAt" />
<result column="file_size" jdbcType="BIGINT" property="fileSize" />
<result column="file_sha1" jdbcType="VARCHAR" property="fileSha1" />
</resultMap>
<sql id="Base_Column_List">
<!--
WARNING - @mbg.generated
This element is automatically generated by MyBatis Generator, do not modify.
-->
id, book_id, file_display_name, file_name, file_format, number_of_pages, watermark,
advertising, book_origin, file_create_at, file_modified_at, file_size, file_sha1
id, book_id, file_name, file_ext, file_size, file_sha1, number_of_pages, watermark,
advertising, `source`, file_create_at, file_modified_at
</sql>
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
<!--
@@ -51,16 +50,16 @@
WARNING - @mbg.generated
This element is automatically generated by MyBatis Generator, do not modify.
-->
insert into file_info (id, book_id, file_display_name,
file_name, file_format, number_of_pages,
watermark, advertising, book_origin,
file_create_at, file_modified_at, file_size,
file_sha1)
values (#{id,jdbcType=INTEGER}, #{bookId,jdbcType=INTEGER}, #{fileDisplayName,jdbcType=VARCHAR},
#{fileName,jdbcType=VARCHAR}, #{fileFormat,jdbcType=VARCHAR}, #{numberOfPages,jdbcType=INTEGER},
#{watermark,jdbcType=BIT}, #{advertising,jdbcType=BIT}, #{bookOrigin,jdbcType=VARCHAR},
#{fileCreateAt,jdbcType=TIMESTAMP}, #{fileModifiedAt,jdbcType=TIMESTAMP}, #{fileSize,jdbcType=BIGINT},
#{fileSha1,jdbcType=VARCHAR})
insert into file_info (id, book_id, file_name,
file_ext, file_size, file_sha1,
number_of_pages, watermark, advertising,
`source`, file_create_at, file_modified_at
)
values (#{id,jdbcType=INTEGER}, #{bookId,jdbcType=INTEGER}, #{fileName,jdbcType=VARCHAR},
#{fileExt,jdbcType=VARCHAR}, #{fileSize,jdbcType=BIGINT}, #{fileSha1,jdbcType=VARCHAR},
#{numberOfPages,jdbcType=INTEGER}, #{watermark,jdbcType=BIT}, #{advertising,jdbcType=BIT},
#{source,jdbcType=VARCHAR}, #{fileCreateAt,jdbcType=TIMESTAMP}, #{fileModifiedAt,jdbcType=TIMESTAMP}
)
</insert>
<insert id="insertSelective" parameterType="plus.bookshelf.Dao.DO.FileDO">
<!--
@@ -75,14 +74,17 @@
<if test="bookId != null">
book_id,
</if>
<if test="fileDisplayName != null">
file_display_name,
</if>
<if test="fileName != null">
file_name,
</if>
<if test="fileFormat != null">
file_format,
<if test="fileExt != null">
file_ext,
</if>
<if test="fileSize != null">
file_size,
</if>
<if test="fileSha1 != null">
file_sha1,
</if>
<if test="numberOfPages != null">
number_of_pages,
@@ -93,8 +95,8 @@
<if test="advertising != null">
advertising,
</if>
<if test="bookOrigin != null">
book_origin,
<if test="source != null">
`source`,
</if>
<if test="fileCreateAt != null">
file_create_at,
@@ -102,12 +104,6 @@
<if test="fileModifiedAt != null">
file_modified_at,
</if>
<if test="fileSize != null">
file_size,
</if>
<if test="fileSha1 != null">
file_sha1,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
@@ -116,14 +112,17 @@
<if test="bookId != null">
#{bookId,jdbcType=INTEGER},
</if>
<if test="fileDisplayName != null">
#{fileDisplayName,jdbcType=VARCHAR},
</if>
<if test="fileName != null">
#{fileName,jdbcType=VARCHAR},
</if>
<if test="fileFormat != null">
#{fileFormat,jdbcType=VARCHAR},
<if test="fileExt != null">
#{fileExt,jdbcType=VARCHAR},
</if>
<if test="fileSize != null">
#{fileSize,jdbcType=BIGINT},
</if>
<if test="fileSha1 != null">
#{fileSha1,jdbcType=VARCHAR},
</if>
<if test="numberOfPages != null">
#{numberOfPages,jdbcType=INTEGER},
@@ -134,8 +133,8 @@
<if test="advertising != null">
#{advertising,jdbcType=BIT},
</if>
<if test="bookOrigin != null">
#{bookOrigin,jdbcType=VARCHAR},
<if test="source != null">
#{source,jdbcType=VARCHAR},
</if>
<if test="fileCreateAt != null">
#{fileCreateAt,jdbcType=TIMESTAMP},
@@ -143,12 +142,6 @@
<if test="fileModifiedAt != null">
#{fileModifiedAt,jdbcType=TIMESTAMP},
</if>
<if test="fileSize != null">
#{fileSize,jdbcType=BIGINT},
</if>
<if test="fileSha1 != null">
#{fileSha1,jdbcType=VARCHAR},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="plus.bookshelf.Dao.DO.FileDO">
@@ -161,14 +154,17 @@
<if test="bookId != null">
book_id = #{bookId,jdbcType=INTEGER},
</if>
<if test="fileDisplayName != null">
file_display_name = #{fileDisplayName,jdbcType=VARCHAR},
</if>
<if test="fileName != null">
file_name = #{fileName,jdbcType=VARCHAR},
</if>
<if test="fileFormat != null">
file_format = #{fileFormat,jdbcType=VARCHAR},
<if test="fileExt != null">
file_ext = #{fileExt,jdbcType=VARCHAR},
</if>
<if test="fileSize != null">
file_size = #{fileSize,jdbcType=BIGINT},
</if>
<if test="fileSha1 != null">
file_sha1 = #{fileSha1,jdbcType=VARCHAR},
</if>
<if test="numberOfPages != null">
number_of_pages = #{numberOfPages,jdbcType=INTEGER},
@@ -179,8 +175,8 @@
<if test="advertising != null">
advertising = #{advertising,jdbcType=BIT},
</if>
<if test="bookOrigin != null">
book_origin = #{bookOrigin,jdbcType=VARCHAR},
<if test="source != null">
`source` = #{source,jdbcType=VARCHAR},
</if>
<if test="fileCreateAt != null">
file_create_at = #{fileCreateAt,jdbcType=TIMESTAMP},
@@ -188,12 +184,6 @@
<if test="fileModifiedAt != null">
file_modified_at = #{fileModifiedAt,jdbcType=TIMESTAMP},
</if>
<if test="fileSize != null">
file_size = #{fileSize,jdbcType=BIGINT},
</if>
<if test="fileSha1 != null">
file_sha1 = #{fileSha1,jdbcType=VARCHAR},
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
@@ -204,17 +194,16 @@
-->
update file_info
set book_id = #{bookId,jdbcType=INTEGER},
file_display_name = #{fileDisplayName,jdbcType=VARCHAR},
file_name = #{fileName,jdbcType=VARCHAR},
file_format = #{fileFormat,jdbcType=VARCHAR},
file_ext = #{fileExt,jdbcType=VARCHAR},
file_size = #{fileSize,jdbcType=BIGINT},
file_sha1 = #{fileSha1,jdbcType=VARCHAR},
number_of_pages = #{numberOfPages,jdbcType=INTEGER},
watermark = #{watermark,jdbcType=BIT},
advertising = #{advertising,jdbcType=BIT},
book_origin = #{bookOrigin,jdbcType=VARCHAR},
`source` = #{source,jdbcType=VARCHAR},
file_create_at = #{fileCreateAt,jdbcType=TIMESTAMP},
file_modified_at = #{fileModifiedAt,jdbcType=TIMESTAMP},
file_size = #{fileSize,jdbcType=BIGINT},
file_sha1 = #{fileSha1,jdbcType=VARCHAR}
file_modified_at = #{fileModifiedAt,jdbcType=TIMESTAMP}
where id = #{id,jdbcType=INTEGER}
</update>
<select id="selectAvailableByBookId" resultMap="BaseResultMap">
@@ -234,6 +223,12 @@
from file_info
where file_sha1 = #{fileSha1,jdbcType=VARCHAR} or file_sha1 is null or file_sha1 = ''
</select>
<select id="selectBySha1" parameterType="java.lang.String" resultMap="BaseResultMap">
select
<include refid="Base_Column_List" />
from file_info
where file_sha1 = #{fileSha1,jdbcType=VARCHAR}
</select>
<select id="getLastInsertId" resultType="java.lang.Integer">
SELECT LAST_INSERT_ID();
</select>
@@ -242,4 +237,9 @@
set book_id = 0
where book_id = #{bookId,jdbcType=INTEGER}
</update>
<update id="updateFileSha1" parameterType="java.lang.Integer">
update file_info
set file_sha1 = #{fileSha1,jdbcType=VARCHAR}
where id = #{id,jdbcType=INTEGER}
</update>
</mapper>

View File

@@ -8,25 +8,20 @@
-->
<id column="id" jdbcType="INTEGER" property="id" />
<result column="file_id" jdbcType="INTEGER" property="fileId" />
<result column="file_name" jdbcType="VARCHAR" property="fileName" />
<result column="file_size" jdbcType="BIGINT" property="fileSize" />
<result column="file_type" jdbcType="VARCHAR" property="fileType" />
<result column="storage_medium_type" jdbcType="VARCHAR" property="storageMediumType" />
<result column="upload_status" jdbcType="VARCHAR" property="uploadStatus" />
<result column="storage_medium" jdbcType="VARCHAR" property="storageMedium" />
<result column="file_path" jdbcType="VARCHAR" property="filePath" />
<result column="file_pwd" jdbcType="VARCHAR" property="filePwd" />
<result column="file_share_code" jdbcType="VARCHAR" property="fileShareCode" />
<result column="upload_status" jdbcType="VARCHAR" property="uploadStatus" />
<result column="file_sha1" jdbcType="VARCHAR" property="fileSha1" />
<result column="last_modified" jdbcType="BIGINT" property="lastModified" />
<result column="additional_fields" jdbcType="VARCHAR" property="additionalFields" />
</resultMap>
<sql id="Base_Column_List">
<!--
WARNING - @mbg.generated
This element is automatically generated by MyBatis Generator, do not modify.
-->
id, file_id, file_name, file_size, file_type, storage_medium_type, file_path, file_pwd,
file_share_code, upload_status, file_sha1, last_modified, additional_fields
id, file_id, upload_status, storage_medium, file_path, file_pwd, file_share_code,
last_modified
</sql>
<select id="selectByPrimaryKey" parameterType="java.lang.Integer" resultMap="BaseResultMap">
<!--
@@ -51,16 +46,12 @@
WARNING - @mbg.generated
This element is automatically generated by MyBatis Generator, do not modify.
-->
insert into file_object_info (id, file_id, file_name,
file_size, file_type, storage_medium_type,
file_path, file_pwd, file_share_code,
upload_status, file_sha1, last_modified,
additional_fields)
values (#{id,jdbcType=INTEGER}, #{fileId,jdbcType=INTEGER}, #{fileName,jdbcType=VARCHAR},
#{fileSize,jdbcType=BIGINT}, #{fileType,jdbcType=VARCHAR}, #{storageMediumType,jdbcType=VARCHAR},
#{filePath,jdbcType=VARCHAR}, #{filePwd,jdbcType=VARCHAR}, #{fileShareCode,jdbcType=VARCHAR},
#{uploadStatus,jdbcType=VARCHAR}, #{fileSha1,jdbcType=VARCHAR}, #{lastModified,jdbcType=BIGINT},
#{additionalFields,jdbcType=VARCHAR})
insert into file_object_info (id, file_id, upload_status,
storage_medium, file_path, file_pwd,
file_share_code, last_modified)
values (#{id,jdbcType=INTEGER}, #{fileId,jdbcType=INTEGER}, #{uploadStatus,jdbcType=VARCHAR},
#{storageMedium,jdbcType=VARCHAR}, #{filePath,jdbcType=VARCHAR}, #{filePwd,jdbcType=VARCHAR},
#{fileShareCode,jdbcType=VARCHAR}, #{lastModified,jdbcType=BIGINT})
</insert>
<insert id="insertSelective" parameterType="plus.bookshelf.Dao.DO.FileObjectDO">
<!--
@@ -75,17 +66,11 @@
<if test="fileId != null">
file_id,
</if>
<if test="fileName != null">
file_name,
<if test="uploadStatus != null">
upload_status,
</if>
<if test="fileSize != null">
file_size,
</if>
<if test="fileType != null">
file_type,
</if>
<if test="storageMediumType != null">
storage_medium_type,
<if test="storageMedium != null">
storage_medium,
</if>
<if test="filePath != null">
file_path,
@@ -96,18 +81,9 @@
<if test="fileShareCode != null">
file_share_code,
</if>
<if test="uploadStatus != null">
upload_status,
</if>
<if test="fileSha1 != null">
file_sha1,
</if>
<if test="lastModified != null">
last_modified,
</if>
<if test="additionalFields != null">
additional_fields,
</if>
</trim>
<trim prefix="values (" suffix=")" suffixOverrides=",">
<if test="id != null">
@@ -116,17 +92,11 @@
<if test="fileId != null">
#{fileId,jdbcType=INTEGER},
</if>
<if test="fileName != null">
#{fileName,jdbcType=VARCHAR},
<if test="uploadStatus != null">
#{uploadStatus,jdbcType=VARCHAR},
</if>
<if test="fileSize != null">
#{fileSize,jdbcType=BIGINT},
</if>
<if test="fileType != null">
#{fileType,jdbcType=VARCHAR},
</if>
<if test="storageMediumType != null">
#{storageMediumType,jdbcType=VARCHAR},
<if test="storageMedium != null">
#{storageMedium,jdbcType=VARCHAR},
</if>
<if test="filePath != null">
#{filePath,jdbcType=VARCHAR},
@@ -137,18 +107,9 @@
<if test="fileShareCode != null">
#{fileShareCode,jdbcType=VARCHAR},
</if>
<if test="uploadStatus != null">
#{uploadStatus,jdbcType=VARCHAR},
</if>
<if test="fileSha1 != null">
#{fileSha1,jdbcType=VARCHAR},
</if>
<if test="lastModified != null">
#{lastModified,jdbcType=BIGINT},
</if>
<if test="additionalFields != null">
#{additionalFields,jdbcType=VARCHAR},
</if>
</trim>
</insert>
<update id="updateByPrimaryKeySelective" parameterType="plus.bookshelf.Dao.DO.FileObjectDO">
@@ -161,17 +122,11 @@
<if test="fileId != null">
file_id = #{fileId,jdbcType=INTEGER},
</if>
<if test="fileName != null">
file_name = #{fileName,jdbcType=VARCHAR},
<if test="uploadStatus != null">
upload_status = #{uploadStatus,jdbcType=VARCHAR},
</if>
<if test="fileSize != null">
file_size = #{fileSize,jdbcType=BIGINT},
</if>
<if test="fileType != null">
file_type = #{fileType,jdbcType=VARCHAR},
</if>
<if test="storageMediumType != null">
storage_medium_type = #{storageMediumType,jdbcType=VARCHAR},
<if test="storageMedium != null">
storage_medium = #{storageMedium,jdbcType=VARCHAR},
</if>
<if test="filePath != null">
file_path = #{filePath,jdbcType=VARCHAR},
@@ -182,18 +137,9 @@
<if test="fileShareCode != null">
file_share_code = #{fileShareCode,jdbcType=VARCHAR},
</if>
<if test="uploadStatus != null">
upload_status = #{uploadStatus,jdbcType=VARCHAR},
</if>
<if test="fileSha1 != null">
file_sha1 = #{fileSha1,jdbcType=VARCHAR},
</if>
<if test="lastModified != null">
last_modified = #{lastModified,jdbcType=BIGINT},
</if>
<if test="additionalFields != null">
additional_fields = #{additionalFields,jdbcType=VARCHAR},
</if>
</set>
where id = #{id,jdbcType=INTEGER}
</update>
@@ -204,17 +150,12 @@
-->
update file_object_info
set file_id = #{fileId,jdbcType=INTEGER},
file_name = #{fileName,jdbcType=VARCHAR},
file_size = #{fileSize,jdbcType=BIGINT},
file_type = #{fileType,jdbcType=VARCHAR},
storage_medium_type = #{storageMediumType,jdbcType=VARCHAR},
upload_status = #{uploadStatus,jdbcType=VARCHAR},
storage_medium = #{storageMedium,jdbcType=VARCHAR},
file_path = #{filePath,jdbcType=VARCHAR},
file_pwd = #{filePwd,jdbcType=VARCHAR},
file_share_code = #{fileShareCode,jdbcType=VARCHAR},
upload_status = #{uploadStatus,jdbcType=VARCHAR},
file_sha1 = #{fileSha1,jdbcType=VARCHAR},
last_modified = #{lastModified,jdbcType=BIGINT},
additional_fields = #{additionalFields,jdbcType=VARCHAR}
last_modified = #{lastModified,jdbcType=BIGINT}
where id = #{id,jdbcType=INTEGER}
</update>
<select id="selectAll" resultMap="BaseResultMap">
@@ -235,4 +176,7 @@
WHERE file_id IN (SELECT id AS file_id FROM `file_info` WHERE book_id = 1)
AND upload_status = 'SUCCESS'
</select>
<select id="getLastInsertId" resultType="java.lang.Integer">
SELECT LAST_INSERT_ID();
</select>
</mapper>