mirror of
https://github.com/rustfs/console.git
synced 2026-08-29 03:52:28 +08:00
7837930e8c
Add conservative upload content-type handling that appends charset=utf-8 only when text uploads validate as UTF-8, while preserving existing charsets and non-UTF-8 text metadata. Fixes rustfs/rustfs#3095
78 lines
2.0 KiB
JavaScript
78 lines
2.0 KiB
JavaScript
const EXTENSION_MIME_TYPES = {
|
|
txt: "text/plain",
|
|
md: "text/markdown",
|
|
markdown: "text/markdown",
|
|
csv: "text/csv",
|
|
json: "application/json",
|
|
jsonl: "application/x-ndjson",
|
|
ndjson: "application/x-ndjson",
|
|
xml: "application/xml",
|
|
html: "text/html",
|
|
htm: "text/html",
|
|
css: "text/css",
|
|
js: "application/javascript",
|
|
mjs: "application/javascript",
|
|
svg: "image/svg+xml",
|
|
yml: "application/yaml",
|
|
yaml: "application/yaml",
|
|
}
|
|
|
|
function inferMimeTypeFromObjectKey(objectKey) {
|
|
const ext = objectKey.split(".").pop()?.toLowerCase() ?? ""
|
|
return EXTENSION_MIME_TYPES[ext] ?? "application/octet-stream"
|
|
}
|
|
|
|
function hasCharset(contentType) {
|
|
return /(?:^|;)\s*charset\s*=/i.test(contentType)
|
|
}
|
|
|
|
function isTextualContentType(contentType) {
|
|
const mime = contentType.split(";")[0]?.trim().toLowerCase() ?? ""
|
|
return (
|
|
mime.startsWith("text/") ||
|
|
mime === "application/json" ||
|
|
mime === "application/ld+json" ||
|
|
mime === "application/xml" ||
|
|
mime.endsWith("+xml") ||
|
|
mime === "application/javascript" ||
|
|
mime === "application/x-javascript" ||
|
|
mime === "application/ecmascript" ||
|
|
mime === "application/x-ndjson" ||
|
|
mime === "application/ndjson" ||
|
|
mime === "application/yaml" ||
|
|
mime === "application/x-yaml" ||
|
|
mime === "image/svg+xml"
|
|
)
|
|
}
|
|
|
|
async function isValidUtf8(file) {
|
|
const decoder = new TextDecoder("utf-8", { fatal: true })
|
|
const reader = file.stream().getReader()
|
|
try {
|
|
while (true) {
|
|
const { done, value } = await reader.read()
|
|
if (done) break
|
|
decoder.decode(value, { stream: true })
|
|
}
|
|
decoder.decode()
|
|
return true
|
|
} catch {
|
|
return false
|
|
} finally {
|
|
reader.releaseLock()
|
|
}
|
|
}
|
|
|
|
export async function getUploadContentType(file, objectKey) {
|
|
const baseContentType = file.type || inferMimeTypeFromObjectKey(objectKey)
|
|
if (!isTextualContentType(baseContentType) || hasCharset(baseContentType)) {
|
|
return baseContentType
|
|
}
|
|
|
|
if (!(await isValidUtf8(file))) {
|
|
return baseContentType
|
|
}
|
|
|
|
return `${baseContentType}; charset=utf-8`
|
|
}
|