feat: Initial commit of PDF Tools project

This commit is contained in:
2025-08-25 02:29:48 +08:00
parent af6827cd9e
commit 30180e50a2
48 changed files with 36364 additions and 1 deletions

200
server/routes/conversion.js Normal file
View File

@@ -0,0 +1,200 @@
const express = require('express');
const { v4: uuidv4 } = require('uuid');
const { optionalAuth } = require('../middleware/auth');
const conversionService = require('../services/conversionService');
const ConversionTask = require('../models/ConversionTask');
const File = require('../models/File');
const router = express.Router();
/**
* @route POST /api/convert/start
* @desc 开始一个新的文件转换任务
* @access Private (optional)
*/
router.post('/start', optionalAuth, async (req, res, next) => {
try {
const { fileId, outputFormat, options = {} } = req.body;
if (!fileId || !outputFormat) {
return res.status(400).json({ success: false, message: '缺少必要参数fileId和outputFormat' });
}
// 验证文件是否存在
const file = await File.findOne({ fileId });
if (!file) {
return res.status(404).json({ success: false, message: '文件未找到' });
}
// 创建转换任务
const task = await ConversionTask.create({
taskId: uuidv4(),
fileId,
outputFormat,
options,
userId: req.user?.userId || null,
sourceFile: {
name: file.fileName,
size: file.size,
type: file.mimeType
}
});
// 异步开始转换,不阻塞响应
conversionService.startConversion(task.taskId);
res.status(202).json({
success: true,
message: '转换任务已创建',
data: {
taskId: task.taskId,
status: task.status,
progress: task.progress
}
});
} catch (error) {
next(error);
}
});
/**
* @route GET /api/convert/status/:taskId
* @desc 查询转换任务的状态
* @access Public
*/
router.get('/status/:taskId', async (req, res, next) => {
try {
const { taskId } = req.params;
const task = await ConversionTask.findOne({ taskId }).lean();
if (!task) {
return res.status(404).json({ success: false, message: '转换任务未找到' });
}
res.json({ success: true, data: task });
} catch (error) {
next(error);
}
});
/**
* @route GET /api/convert/result/:taskId
* @desc 获取转换任务的结果
* @access Public
*/
router.get('/result/:taskId', async (req, res, next) => {
try {
const { taskId } = req.params;
const task = await ConversionTask.findOne({ taskId }).lean();
if (!task) {
return res.status(404).json({ success: false, message: '转换任务未找到' });
}
if (task.status !== 'completed') {
return res.status(400).json({ success: false, message: '转换尚未完成' });
}
res.json({
success: true,
data: {
taskId: task.taskId,
resultUrl: task.resultFile.downloadUrl,
fileName: task.resultFile.fileName,
fileSize: task.resultFile.fileSize
}
});
} catch (error) {
next(error);
}
});
/**
* @route POST /api/convert/batch
* @desc 开始批量转换任务
* @access Private (optional)
*/
router.post('/batch', optionalAuth, async (req, res, next) => {
try {
const { fileIds, outputFormat, options = {} } = req.body;
if (!fileIds || !Array.isArray(fileIds) || fileIds.length === 0) {
return res.status(400).json({ success: false, message: '请提供要转换的文件ID列表' });
}
if (fileIds.length > 10) {
return res.status(400).json({ success: false, message: '批量转换最多支持10个文件' });
}
const batchId = uuidv4();
const createdTasks = [];
for (const fileId of fileIds) {
const file = await File.findOne({ fileId });
if (file) {
const task = await ConversionTask.create({
taskId: uuidv4(),
batchId,
fileId,
outputFormat,
options,
userId: req.user?.userId || null,
sourceFile: {
name: file.fileName,
size: file.size,
type: file.mimeType
}
});
createdTasks.push(task);
// 异步开始转换
conversionService.startConversion(task.taskId);
}
}
res.status(202).json({
success: true,
message: '批量转换任务已创建',
data: {
batchId,
taskCount: createdTasks.length,
tasks: createdTasks.map(t => ({ taskId: t.taskId, status: t.status }))
}
});
} catch (error) {
next(error);
}
});
/**
* @route POST /api/convert/cancel/:taskId
* @desc 取消一个正在进行的转换任务
* @access Private (optional)
*/
router.post('/cancel/:taskId', optionalAuth, async (req, res, next) => {
try {
const { taskId } = req.params;
const task = await ConversionTask.findOne({ taskId });
if (!task) {
return res.status(404).json({ success: false, message: '转换任务未找到' });
}
// 权限检查:确保用户只能取消自己的任务
if (task.userId && (!req.user || task.userId !== req.user.userId)) {
return res.status(403).json({ success: false, message: '无权操作此任务' });
}
await task.cancel();
res.json({ success: true, message: '转换任务已取消' });
} catch (error) {
next(error);
}
});
module.exports = router;