fix: view route title & handle unicode characters in raw route (#980)

* fix: prioritize file original name in view route title

* fix: update Content-Disposition header to support unicode characters
fix: display issue with raw route when text contains unicode characters

---------

Co-authored-by: dicedtomato <35403473+diced@users.noreply.github.com>
This commit is contained in:
Huang Cheng Ting
2026-02-06 08:05:49 +08:00
committed by GitHub
parent 2332d529e0
commit 1f672cda3a
4 changed files with 21 additions and 16 deletions

View File

@@ -56,7 +56,7 @@ export default function ViewFileId() {
const [passwordError, setPasswordError] = useState<string>('');
const [detailsOpen, setDetailsOpen] = useState<boolean>(false);
useTitle(file.name ?? 'View File');
useTitle(file.originalName ?? file.name ?? 'View File');
return password && !pw ? (
<Modal onClose={() => {}} opened={true} withCloseButton={false} centered title='Password required'>
@@ -101,7 +101,7 @@ export default function ViewFileId() {
<>
<Paper withBorder style={{ borderTop: 0, borderLeft: 0, borderRight: 0 }}>
<Group justify='space-between' py={5} px='xs'>
<Text c='dimmed'>{file.name}</Text>
<Text c='dimmed'>{file.originalName ?? file.name}</Text>
<Group>
<ActionIcon size='md' variant='outline' onClick={() => setDetailsOpen((o) => !o)}>
@@ -167,7 +167,7 @@ export default function ViewFileId() {
<Group justify='space-between' mb='sm'>
<Group>
<Text size='lg' fw={700} display='flex'>
{file.name}{' '}
{file.originalName ?? file.name}{' '}
</Text>
{user?.view!.showTags && (
<Group gap={4}>

View File

@@ -276,7 +276,7 @@ export default typedPlugin(
}
return res
.header('Content-Disposition', `attachment; filename="zipline4_export_${Date.now()}.json"`)
.header('Content-Disposition', `attachment; filename*=utf-8''zipline4_export_${Date.now()}.json`)
.type('application/json')
.send(export4);
},

View File

@@ -117,6 +117,8 @@ export default typedPlugin(
}
const size = file?.size || (await datasource.size(file?.name ?? id));
const fileType = file?.type || 'application/octet-stream';
const contentType = fileType.startsWith('text/') ? `${fileType}; charset=utf-8` : fileType;
if (req.headers.range) {
const [start, end] = parseRange(req.headers.range, size);
@@ -125,12 +127,12 @@ export default typedPlugin(
if (!buf) return res.callNotFound();
return res
.type(file?.type || 'application/octet-stream')
.type(contentType)
.headers({
'Content-Length': size,
...(file?.originalName
? {
'Content-Disposition': `${download ? 'attachment; ' : ''}filename="${encodeURIComponent(file.originalName)}"`,
'Content-Disposition': `${download ? 'attachment; ' : ''}filename*=utf-8''${encodeURIComponent(file.originalName)}`,
}
: download && {
'Content-Disposition': 'attachment;',
@@ -144,14 +146,14 @@ export default typedPlugin(
if (!buf) return res.callNotFound();
return res
.type(file?.type || 'application/octet-stream')
.type(contentType)
.headers({
'Content-Range': `bytes ${start}-${end}/${size}`,
'Accept-Ranges': 'bytes',
'Content-Length': end - start + 1,
...(file?.originalName
? {
'Content-Disposition': `${download ? 'attachment; ' : ''}filename="${encodeURIComponent(file.originalName)}"`,
'Content-Disposition': `${download ? 'attachment; ' : ''}filename*=utf-8''${encodeURIComponent(file.originalName)}`,
}
: download && {
'Content-Disposition': 'attachment;',
@@ -165,13 +167,13 @@ export default typedPlugin(
if (!buf) return res.callNotFound();
return res
.type(file?.type || 'application/octet-stream')
.type(contentType)
.headers({
'Content-Length': size,
'Accept-Ranges': 'bytes',
...(file?.originalName
? {
'Content-Disposition': `${download ? 'attachment; ' : ''}filename="${encodeURIComponent(file.originalName)}"`,
'Content-Disposition': `${download ? 'attachment; ' : ''}filename*=utf-8''${encodeURIComponent(file.originalName)}`,
}
: download && {
'Content-Disposition': 'attachment;',

View File

@@ -124,6 +124,9 @@ export const rawFileHandler = async (
}
};
const fileType = file?.type || 'application/octet-stream';
const contentType = fileType.startsWith('text/') ? `${fileType}; charset=utf-8` : fileType;
if (req.headers.range) {
const [start, end] = parseRange(req.headers.range, size);
if (start >= size || end >= size) {
@@ -133,12 +136,12 @@ export const rawFileHandler = async (
await countView();
return res
.type(file?.type || 'application/octet-stream')
.type(contentType)
.headers({
'Content-Length': size,
...(file?.originalName
? {
'Content-Disposition': `${download ? 'attachment; ' : ''}filename="${encodeURIComponent(file.originalName)}"`,
'Content-Disposition': `${download ? 'attachment; ' : ''}filename*=utf-8''${encodeURIComponent(file.originalName)}`,
}
: download && { 'Content-Disposition': 'attachment;' }),
})
@@ -152,14 +155,14 @@ export const rawFileHandler = async (
await countView();
return res
.type(file?.type || 'application/octet-stream')
.type(contentType)
.headers({
'Content-Range': `bytes ${start}-${end}/${size}`,
'Accept-Ranges': 'bytes',
'Content-Length': end - start + 1,
...(file?.originalName
? {
'Content-Disposition': `${download ? 'attachment; ' : ''}filename="${encodeURIComponent(file.originalName)}"`,
'Content-Disposition': `${download ? 'attachment; ' : ''}filename*=utf-8''${encodeURIComponent(file.originalName)}`,
}
: download && { 'Content-Disposition': 'attachment;' }),
})
@@ -173,13 +176,13 @@ export const rawFileHandler = async (
await countView();
return res
.type(file?.type || 'application/octet-stream')
.type(contentType)
.headers({
'Content-Length': size,
'Accept-Ranges': 'bytes',
...(file?.originalName
? {
'Content-Disposition': `${download ? 'attachment; ' : ''}filename="${encodeURIComponent(file.originalName)}"`,
'Content-Disposition': `${download ? 'attachment; ' : ''}filename*=utf-8''${encodeURIComponent(file.originalName)}`,
}
: download && { 'Content-Disposition': 'attachment;' }),
})