Files
pdf-tools/server/routes/conversion.js

201 lines
5.1 KiB
JavaScript
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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;