修复报销附件上传与中文文件名(07-28-travel-reimbursement-guide)
这个提交包含在:
@@ -6,6 +6,7 @@ const { AppError } = require("../utils/AppError");
|
||||
const { sendData } = require("../utils/reply");
|
||||
const { buildAuditLogData } = require("../utils/audit");
|
||||
const { sha256Hex } = require("../utils/crypto");
|
||||
const { buildAttachmentContentDisposition } = require("../utils/contentDisposition");
|
||||
const { compactDateString, currentDateString, parseDateOnlyString } = require("../utils/date");
|
||||
const { findActiveDelegationForDelegate, listActiveDelegationPrincipals } = require("../utils/delegation");
|
||||
const { hasPermission, resolveEntityPermission } = require("../constants/permissions");
|
||||
@@ -293,11 +294,6 @@ function ensureApplicantOrAdmin(request, reimbursement) {
|
||||
}
|
||||
}
|
||||
|
||||
function sanitizeAttachmentFilename(fileName) {
|
||||
if (!fileName) return "file";
|
||||
return fileName.replace(/[\r\n"]/g, "_");
|
||||
}
|
||||
|
||||
function mapReimbursementAttachment(item) {
|
||||
return {
|
||||
id: item.id,
|
||||
@@ -2481,7 +2477,12 @@ async function reimbursementRoutes(fastify) {
|
||||
const files = [];
|
||||
let governanceFields = {};
|
||||
try {
|
||||
for await (const part of request.parts()) {
|
||||
for await (const part of request.parts({
|
||||
limits: {
|
||||
files: 5,
|
||||
fileSize: fastify.config.maxUploadSizeBytes,
|
||||
},
|
||||
})) {
|
||||
if (part.type === "field") {
|
||||
governanceFields = parseMultipartGovernanceField(part, governanceFields);
|
||||
continue;
|
||||
@@ -2533,6 +2534,14 @@ async function reimbursementRoutes(fastify) {
|
||||
});
|
||||
}
|
||||
} catch (error) {
|
||||
if (error?.code === "FST_FILES_LIMIT") {
|
||||
throw new AppError({
|
||||
code: "VALID_001",
|
||||
message: "参数校验失败",
|
||||
statusCode: 400,
|
||||
details: { file: "too_many_files", maxFiles: 5 },
|
||||
});
|
||||
}
|
||||
if (error?.code === "FST_REQ_FILE_TOO_LARGE") {
|
||||
throw new AppError({
|
||||
code: "VALID_001",
|
||||
@@ -2809,7 +2818,7 @@ async function reimbursementRoutes(fastify) {
|
||||
reply.type(attachment.mime_type || "application/octet-stream");
|
||||
reply.header(
|
||||
"content-disposition",
|
||||
`inline; filename=\"${sanitizeAttachmentFilename(attachment.original_name)}\"`,
|
||||
buildAttachmentContentDisposition(attachment.original_name, { disposition: "inline" }),
|
||||
);
|
||||
return reply.send(stream);
|
||||
},
|
||||
|
||||
在新工单中引用
屏蔽一个用户