You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

223 lines
5.9 KiB

11 months ago
11 months ago
11 months ago
11 months ago
11 months ago
  1. const multer = require("multer");
  2. const path = require("path");
  3. const fs = require("fs");
  4. const { v4 } = require("uuid");
  5. const { normalizePath } = require(".");
  6. /**
  7. * Handle File uploads for auto-uploading.
  8. * Mostly used for internal GUI/API uploads.
  9. */
  10. const fileUploadStorage = multer.diskStorage({
  11. destination: function (_, __, cb) {
  12. const uploadOutput =
  13. process.env.NODE_ENV ==="development"
  14. ? path.resolve(__dirname, "../../storage/hotdir")
  15. : path.resolve(process.env.STORAGE_DIR, "hotdir");
  16. cb(null, uploadOutput);
  17. },
  18. filename: function (_, file, cb) {
  19. file.originalname = normalizePath(
  20. Buffer.from(file.originalname, "latin1").toString("utf8")
  21. );
  22. cb(null, file.originalname);
  23. },
  24. });
  25. /**
  26. * Handle API file upload as documents - this does not manipulate the filename
  27. * at all for encoding/charset reasons.
  28. */
  29. const fileAPIUploadStorage = multer.diskStorage({
  30. destination: function (_, __, cb) {
  31. const uploadOutput =
  32. process.env.NODE_ENV ==="development"
  33. ? path.resolve(__dirname, "../../storage/hotdir")
  34. : path.resolve(process.env.STORAGE_DIR, "hotdir");
  35. cb(null, uploadOutput);
  36. },
  37. filename: function (_, file, cb) {
  38. file.originalname = normalizePath(file.originalname);
  39. cb(null, file.originalname);
  40. },
  41. });
  42. // Asset storage for logos
  43. const assetUploadStorage = multer.diskStorage({
  44. destination: function (_, __, cb) {
  45. const uploadOutput =
  46. process.env.NODE_ENV === "development"
  47. ? path.resolve(__dirname, `../../storage/assets`)
  48. : path.resolve(process.env.STORAGE_DIR, "assets");
  49. fs.mkdirSync(uploadOutput, { recursive: true });
  50. return cb(null, uploadOutput);
  51. },
  52. filename: function (_, file, cb) {
  53. file.originalname = normalizePath(
  54. Buffer.from(file.originalname, "latin1").toString("utf8")
  55. );
  56. cb(null, file.originalname);
  57. },
  58. });
  59. /**
  60. * Handle PFP file upload as logos
  61. */
  62. const pfpUploadStorage = multer.diskStorage({
  63. destination: function (_, __, cb) {
  64. const uploadOutput =
  65. process.env.NODE_ENV === "development"
  66. ? path.resolve(__dirname, `../../storage/assets/pfp`)
  67. : path.resolve(process.env.STORAGE_DIR, "assets/pfp");
  68. fs.mkdirSync(uploadOutput, { recursive: true });
  69. return cb(null, uploadOutput);
  70. },
  71. filename: function (req, file, cb) {
  72. const randomFileName = `${v4()}${path.extname(
  73. normalizePath(file.originalname)
  74. )}`;
  75. req.randomFileName = randomFileName;
  76. cb(null, randomFileName);
  77. },
  78. });
  79. /**
  80. * Handle Generic file upload as documents from the GUI
  81. * @param {Request} request
  82. * @param {Response} response
  83. * @param {NextFunction} next
  84. */
  85. function handleFileUpload(request, response, next) {
  86. const upload = multer({ storage: fileUploadStorage }).single("file");
  87. upload(request, response, function (err) {
  88. if (err) {
  89. response
  90. .status(500)
  91. .json({
  92. success: false,
  93. error: `Invalid file upload. ${err.message}`,
  94. })
  95. .end();
  96. return;
  97. }
  98. next();
  99. });
  100. }
  101. /**
  102. * Handle API file upload as documents - this does not manipulate the filename
  103. * at all for encoding/charset reasons.
  104. * @param {Request} request
  105. * @param {Response} response
  106. * @param {NextFunction} next
  107. */
  108. function handleAPIFileUpload(request, response, next) {
  109. const upload = multer({ storage: fileAPIUploadStorage }).single("file");
  110. upload(request, response, function (err) {
  111. if (err) {
  112. response
  113. .status(500)
  114. .json({
  115. success: false,
  116. error: `Invalid file upload. ${err.message}`,
  117. })
  118. .end();
  119. return;
  120. }
  121. next();
  122. });
  123. }
  124. /**
  125. * Handle logo asset uploads
  126. */
  127. function handleAssetUpload(request, response, next) {
  128. const upload = multer({ storage: assetUploadStorage }).single("logo");
  129. upload(request, response, function (err) {
  130. if (err) {
  131. response
  132. .status(500)
  133. .json({
  134. success: false,
  135. error: `Invalid file upload. ${err.message}`,
  136. })
  137. .end();
  138. return;
  139. }
  140. next();
  141. });
  142. }
  143. /**
  144. * Handle PFP file upload as logos
  145. */
  146. function handlePfpUpload(request, response, next) {
  147. const upload = multer({ storage: pfpUploadStorage }).single("file");
  148. upload(request, response, function (err) {
  149. if (err) {
  150. response
  151. .status(500)
  152. .json({
  153. success: false,
  154. error: `Invalid file upload. ${err.message}`,
  155. })
  156. .end();
  157. return;
  158. }
  159. next();
  160. });
  161. }
  162. // 文件存储配置
  163. const commUploadStorage = multer.diskStorage({
  164. destination: async function (_, __, cb) {
  165. try {
  166. const uploadOutput =
  167. process.env.NODE_ENV === "development"
  168. ? path.resolve(__dirname, `../../../server/storage/localFile`)
  169. : path.resolve(process.env.STORAGE_DIR, `../../server/storage/localFile`);
  170. if (process.env.NODE_ENV !== "development" && !process.env.STORAGE_DIR) {
  171. throw new Error("STORAGE_DIR environment variable is required in production.");
  172. }
  173. fs.mkdirSync(uploadOutput, { recursive: true });
  174. cb(null, uploadOutput);
  175. } catch (err) {
  176. cb(err);
  177. }
  178. },
  179. filename: function (req, file, cb) {
  180. const randomFileName = `${v4()}${path.extname(file.originalname)}`;
  181. req.randomFileName = randomFileName;
  182. cb(null, randomFileName);
  183. },
  184. });
  185. // 文件上传中间件
  186. function handleCommUpload(request, response, next) {
  187. const upload = multer({ storage: commUploadStorage, limits: { fileSize: 100 * 1024 * 1024 }, }).single("file");
  188. upload(request, response, function (err) {
  189. console.log("handleCommUpload", err);
  190. if (err) {
  191. response
  192. .status(500)
  193. .json({
  194. success: false,
  195. error: `Invalid file upload. ${err.message}`,
  196. })
  197. .end();
  198. return;
  199. }
  200. next();
  201. });
  202. }
  203. module.exports = {
  204. handleFileUpload,
  205. handleAPIFileUpload,
  206. handleAssetUpload,
  207. handlePfpUpload,
  208. handleCommUpload,
  209. };