| 123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165 |
- const express = require('express')
- const cors = require('cors')
- const multer = require('multer')
- const path = require('path')
- const fs = require('fs-extra')
- const { calculateFileMD5 } = require('./utils.js')
- const { initDatabase, FileService } = require('../database/database.js')
- const app = express()
- const PORT = 3000
- // 初始化数据库
- initDatabase()
- const fileService = new FileService()
- // 确保上传目录存在
- const uploadDir = path.join(process.cwd(), 'uploads')
- fs.ensureDirSync(uploadDir)
- // 配置 multer - 修复中文文件名问题
- const storage = multer.diskStorage({
- destination: (req, file, cb) => {
- cb(null, uploadDir)
- },
- filename: (req, file, cb) => {
- // 处理中文文件名 - 使用原始文件名但确保安全
- const originalName = Buffer.from(file.originalname, 'latin1').toString('utf8')
- const ext = path.extname(originalName)
- const name = path.basename(originalName, ext)
- // 清理文件名,移除特殊字符
- const safeName = name.replace(/[^a-zA-Z0-9\u4e00-\u9fa5]/g, '_')
- const uniqueSuffix = Date.now() + '-' + Math.round(Math.random() * 1E9)
- const filename = safeName + '-' + uniqueSuffix + ext
- cb(null, filename)
- }
- })
- const upload = multer({
- storage,
- fileFilter: (req, file, cb) => {
- // 处理文件名编码
- file.originalname = Buffer.from(file.originalname, 'latin1').toString('utf8')
- cb(null, true)
- }
- })
- // 设置响应头,确保使用 UTF-8 编码
- app.use((req, res, next) => {
- res.setHeader('Content-Type', 'application/json; charset=utf-8')
- next()
- })
- app.use(cors())
- app.use(express.json({ limit: '50mb' }))
- app.use(express.urlencoded({ extended: true, limit: '50mb' }))
- // 文件上传接口
- app.post('/api/upload', upload.single('file'), async (req, res) => {
- try {
- if (!req.file) {
- return res.status(400).json({ error: 'No file uploaded' })
- }
- // 确保文件名正确编码
- const originalName = Buffer.from(req.file.originalname, 'latin1').toString('utf8')
- const fileInfo = {
- originalName: originalName,
- fileName: req.file.filename,
- filePath: req.file.path,
- fileSize: req.file.size,
- mimeType: req.file.mimetype
- }
- // 计算 MD5
- const md5 = await calculateFileMD5(req.file.path)
- // 保存到数据库
- const fileRecord = await fileService.createFile({
- ...fileInfo,
- md5
- })
- res.json({
- success: true,
- data: fileRecord
- })
- } catch (error) {
- console.error('Upload error:', error)
- res.status(500).json({ error: 'Upload failed: ' + error.message })
- }
- })
- // 获取文件列表(分页)
- app.get('/api/files', async (req, res) => {
- try {
- const page = parseInt(req.query.page) || 1
- const pageSize = parseInt(req.query.pageSize) || 10
- const result = await fileService.getFilesPaginated(page, pageSize)
- // 确保返回的数据使用 UTF-8 编码
- res.json(result)
- } catch (error) {
- console.error('Get files error:', error)
- res.status(500).json({ error: 'Failed to get files' })
- }
- })
- // 其他接口保持不变...
- app.post('/api/files/:id/check-md5', async (req, res) => {
- try {
- const fileId = parseInt(req.params.id)
- const file = await fileService.getFileById(fileId)
- if (!file) {
- return res.status(404).json({ error: 'File not found' })
- }
- const currentMD5 = await calculateFileMD5(file.filePath)
- const isChanged = currentMD5 !== file.md5
- res.json({
- isChanged,
- currentMD5,
- originalMD5: file.md5,
- file
- })
- } catch (error) {
- console.error('MD5 check error:', error)
- res.status(500).json({ error: 'MD5 check failed' })
- }
- })
- app.put('/api/files/:id/update-md5', async (req, res) => {
- try {
- const fileId = parseInt(req.params.id)
- const { md5 } = req.body
- await fileService.updateFileMD5(fileId, md5)
- res.json({ success: true })
- } catch (error) {
- console.error('Update MD5 error:', error)
- res.status(500).json({ error: 'Update failed' })
- }
- })
- // 健康检查接口
- app.get('/api/health', (req, res) => {
- res.json({
- status: 'OK',
- timestamp: new Date().toISOString(),
- service: 'file-management-api'
- })
- })
- function startServer() {
- app.listen(PORT, () => {
- console.log(`Server running on http://localhost:${PORT}`)
- })
- }
- module.exports = { startServer }
|