mira-app-core
Version:
Core library for Mira TypeScript project - provides base functionality without auto-execution
209 lines • 9.49 kB
JavaScript
;
var __createBinding = (this && this.__createBinding) || (Object.create ? (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
var desc = Object.getOwnPropertyDescriptor(m, k);
if (!desc || ("get" in desc ? !m.__esModule : desc.writable || desc.configurable)) {
desc = { enumerable: true, get: function() { return m[k]; } };
}
Object.defineProperty(o, k2, desc);
}) : (function(o, m, k, k2) {
if (k2 === undefined) k2 = k;
o[k2] = m[k];
}));
var __setModuleDefault = (this && this.__setModuleDefault) || (Object.create ? (function(o, v) {
Object.defineProperty(o, "default", { enumerable: true, value: v });
}) : function(o, v) {
o["default"] = v;
});
var __importStar = (this && this.__importStar) || (function () {
var ownKeys = function(o) {
ownKeys = Object.getOwnPropertyNames || function (o) {
var ar = [];
for (var k in o) if (Object.prototype.hasOwnProperty.call(o, k)) ar[ar.length] = k;
return ar;
};
return ownKeys(o);
};
return function (mod) {
if (mod && mod.__esModule) return mod;
var result = {};
if (mod != null) for (var k = ownKeys(mod), i = 0; i < k.length; i++) if (k[i] !== "default") __createBinding(result, mod, k[i]);
__setModuleDefault(result, mod);
return result;
};
})();
var __importDefault = (this && this.__importDefault) || function (mod) {
return (mod && mod.__esModule) ? mod : { "default": mod };
};
Object.defineProperty(exports, "__esModule", { value: true });
exports.FileRoutes = void 0;
const express_1 = require("express");
const fs = __importStar(require("fs"));
const path = __importStar(require("path"));
const multer_1 = __importDefault(require("multer"));
class FileRoutes {
constructor(backend) {
this.backend = backend;
this.router = (0, express_1.Router)();
this.setupUpload();
this.setupRoutes();
}
setupUpload() {
// 配置multer文件上传
this.upload = (0, multer_1.default)({
storage: multer_1.default.diskStorage({
destination: (req, file, cb) => {
const tempDir = path.join(this.backend.dataPath, 'temp');
if (!fs.existsSync(tempDir)) {
fs.mkdirSync(tempDir, { recursive: true });
}
cb(null, tempDir);
},
filename: (req, file, cb) => {
// 处理中文名,确保文件名为utf8编码
const originalName = Buffer.from(file.originalname, 'latin1').toString('utf8');
const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9);
cb(null, uniqueSuffix + path.extname(originalName));
}
})
});
}
setupRoutes() {
// 上传文件到资源库
this.router.post('/upload', this.upload.array('files'), async (req, res) => {
const { libraryId, sourcePath } = req.body; // sourcePath是用户的本地文件位置,用来验证是否上传成功
const clientId = req.body.clientId || null;
const fields = req.body.fields ? JSON.parse(req.body.fields) : null;
const payload = req.body.payload ? JSON.parse(req.body.payload) : null;
const obj = this.backend.libraries.get(libraryId);
if (!obj)
return res.status(404).send('Library not found');
// 解析上传的文件
const files = req.files;
if (!files || !files.length)
return res.status(400).send('No files uploaded.');
try {
const results = [];
for (const file of files) {
try {
// 生成唯一文件名并保存文件
const originalName = Buffer.from(file.originalname, 'latin1').toString('utf8');
const { tags, folder_id } = payload.data || {};
const fileData = {
name: req.body.name || originalName,
tags: JSON.stringify(tags || []),
folder_id: folder_id || null,
};
const result = await obj.libraryService.createFileFromPath(file.path, fileData, { importType: 'move' }); // 使用move上传完成后自动删除临时文件
results.push({
success: true,
file: file.path,
result
});
// 发布公告
// 发送WebSocket事件(如果可用)
if (this.backend.webSocketServer) {
this.backend.webSocketServer.broadcastPluginEvent('file::created', {
message: {
type: 'file',
action: 'create',
fields, payload
}, result, libraryId
});
if (clientId) {
const ws = this.backend.webSocketServer?.getWsClientById(libraryId, clientId);
ws && this.backend.webSocketServer?.sendToWebsocket(ws, { eventName: 'file::uploaded', data: { path: sourcePath } });
this.backend.webSocketServer?.broadcastLibraryEvent(libraryId, 'file::created', { ...result, libraryId });
}
}
}
catch (error) {
console.error(`Error processing file ${file.originalname}:`, error);
results.push({
success: false,
file: file.path,
error: error instanceof Error ? error.message : String(error)
});
}
}
res.send({ results });
}
catch (error) {
console.error('Error uploading files:', error);
res.status(500).send('Internal server error while processing the upload.');
}
});
// 获取文件缩略图
this.router.get('/thumb/:libraryId/:id', async (req, res) => {
try {
const ret = await this.parseLibraryItem(req, res);
if (ret) {
const thumbPath = await ret.library.getItemThumbPath(ret.item, { isNetworkImage: false });
if (!fs.existsSync(thumbPath))
return res.status(404).send('Thumbnail not found');
res.setHeader('Content-Type', 'image/png');
fs.createReadStream(thumbPath).pipe(res);
}
}
catch (err) {
console.error('Error serving thumbnail:', err);
res.status(500).send('Internal server error');
}
});
// 获取文件内容
this.router.get('/file/:libraryId/:id', async (req, res) => {
const ret = await this.parseLibraryItem(req, res);
if (ret) {
const filePath = await ret.library.getItemFilePath(ret.item);
if (!filePath || !fs.existsSync(filePath)) {
return res.status(404).send('File not found');
}
const fileExt = path.extname(filePath).toLowerCase();
const contentType = this.getContentType(fileExt);
res.setHeader('Content-Type', contentType);
fs.createReadStream(filePath).pipe(res);
}
});
}
async parseLibraryItem(req, res) {
const { libraryId, id } = req.params;
const obj = this.backend.libraries.get(libraryId);
if (!obj) {
res.status(404).send('Library not found');
return;
}
const item = await obj.libraryService.getFile(parseInt(id));
if (!item) {
res.status(404).send('Item not found');
return;
}
return { library: obj.libraryService, item };
}
getContentType(ext) {
const mimeTypes = {
'.png': 'image/png',
'.jpg': 'image/jpeg',
'.jpeg': 'image/jpeg',
'.gif': 'image/gif',
'.pdf': 'application/pdf',
'.txt': 'text/plain',
'.html': 'text/html',
'.json': 'application/json',
'.mp4': 'video/mp4',
'.mp3': 'audio/mpeg',
'.zip': 'application/zip',
'.doc': 'application/msword',
'.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document',
'.xls': 'application/vnd.ms-excel',
'.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet',
'.ppt': 'application/vnd.ms-powerpoint',
'.pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation'
};
return mimeTypes[ext] || 'application/octet-stream';
}
getRouter() {
return this.router;
}
}
exports.FileRoutes = FileRoutes;
//# sourceMappingURL=FileRoutes.js.map