Force download for lesson materials (Content-Disposition: attachment)

Lesson files were served inline (no Content-Disposition) → browsers
opened PDFs in a new tab instead of downloading; flaky across
browsers/providers. Set Content-Disposition: attachment with the
human-readable filename (RFC 5987 for Cyrillic) on upload.

Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
2026-06-15 16:06:51 +05:00
parent a7abf454d9
commit 5d4630519c
2 changed files with 17 additions and 3 deletions
+12 -1
View File
@@ -17,10 +17,20 @@ export function getPublicUrl(key: string): string {
return `${process.env.S3_ENDPOINT}/${BUCKET}/${key}`;
}
/**
* Заголовок Content-Disposition для принудительного скачивания с человеческим
* именем. RFC 5987: ASCII-фолбэк + UTF-8 (кириллица percent-encoded).
*/
export function attachmentDisposition(filename: string): string {
const ascii = filename.replace(/[^\x20-\x7E]/g, "_").replace(/["\\]/g, "'");
return `attachment; filename="${ascii}"; filename*=UTF-8''${encodeURIComponent(filename)}`;
}
export async function uploadFile(
key: string,
body: Buffer | Uint8Array,
contentType: string
contentType: string,
contentDisposition?: string
): Promise<string> {
await s3.send(
new PutObjectCommand({
@@ -28,6 +38,7 @@ export async function uploadFile(
Key: key,
Body: body,
ContentType: contentType,
...(contentDisposition ? { ContentDisposition: contentDisposition } : {}),
})
);
return getPublicUrl(key);