UploadFaceVideo.js 3.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114
  1. const API = require("../../lib/API")
  2. const { v4: uuidv4 } = require('uuid')
  3. const Redis = require('../../plugin/DataBase/Redis')
  4. const db = require("../../plugin/DataBase/db.js")
  5. const { BaseStdResponse } = require("../../BaseStdResponse")
  6. const multer = require('multer')
  7. const path = require('path')
  8. const fs = require('fs')
  9. const { url } = require("../../config.json")
  10. // 配置 Multer 存储选项
  11. const storage = multer.diskStorage({
  12. destination: (req, file, cb) => {
  13. const { student_num } = req.body
  14. if (!student_num) {
  15. return cb(new Error('缺少参数'))
  16. }
  17. const destPath = path.join('uploads', 'faces', student_num)
  18. fs.mkdirSync(destPath, { recursive: true }) // 确保目录存在
  19. cb(null, destPath)
  20. },
  21. filename: (req, file, cb) => {
  22. const randomName = uuidv4()
  23. cb(null, `${randomName}.webm`)
  24. }
  25. })
  26. // 限制文件类型为 webm
  27. const fileFilter = (req, file, cb) => {
  28. const extname = path.extname(file.originalname).toLowerCase() === ".webm"
  29. const mimetype = file.mimetype === "video/webm"
  30. if (extname && mimetype) {
  31. return cb(null, true)
  32. } else {
  33. cb(new Error('只允许上传 webm 格式的视频'))
  34. }
  35. }
  36. // 初始化 Multer
  37. const upload = multer({
  38. storage: storage,
  39. fileFilter: fileFilter,
  40. limits: { fileSize: 200 * 1024 * 1024 } // 最大 200MB
  41. }).single('upload')
  42. class UploadFaceVideo extends API {
  43. constructor() {
  44. super()
  45. this.noEncrypt()
  46. this.setMethod("POST")
  47. this.setPath("/UploadFaceVideo")
  48. }
  49. async onRequest(req, res) {
  50. upload(req, res, async (err) => {
  51. if (err) {
  52. this.logger.error(`视频上传失败!${err.stack || ''}`)
  53. return res.json({
  54. ...BaseStdResponse.ERR,
  55. msg: err.message ?? '视频上传失败!'
  56. })
  57. }
  58. const { student_num, key } = req.body
  59. if ([student_num, key].some(value => value === '' || value === null || value === undefined)) {
  60. return res.json({
  61. ...BaseStdResponse.MISSING_PARAMETER
  62. })
  63. }
  64. if (!req.file) {
  65. return res.json({
  66. ...BaseStdResponse.MISSING_PARAMETER,
  67. msg: '请上传 webm 视频文件'
  68. })
  69. }
  70. try {
  71. const code = await Redis.get(`faceReco:${student_num}`)
  72. if (!code || code !== key)
  73. return res.json({
  74. ...BaseStdResponse.ERR,
  75. msg: '令牌已过期!请刷新页面重试'
  76. })
  77. await Redis.del(`faceReco:${student_num}`)
  78. } catch (err) {
  79. return res.json({
  80. ...BaseStdResponse.ERR,
  81. msg: '令牌验证失败!请刷新页面重试'
  82. })
  83. }
  84. const videoPath = `/uploads/faces/${student_num}/${req.file.filename}`
  85. const time = new Date().getTime()
  86. let sql = 'INSERT INTO lepao_face (student_num, video_path, create_time, state) VALUES (?, ?, ?, ?)'
  87. let rows = await db.query(sql, [student_num, videoPath, time, 1])
  88. if (!rows || rows.affectedRows !== 1)
  89. return res.json({
  90. ...BaseStdResponse.ERR,
  91. msg: '上传失败,请稍后再试'
  92. })
  93. res.json({
  94. ...BaseStdResponse.OK
  95. })
  96. })
  97. }
  98. }
  99. module.exports.UploadFaceVideo = UploadFaceVideo