Fix iOS download via Content-Disposition header, fix COI gate null check
Some checks failed
Build and Push Docker Image / build (push) Has been cancelled

- Server: presigned GET URLs now include Content-Disposition: attachment header
  when forDownload=true, triggering native browser downloads on all platforms
- Download button uses window.location.href with attachment URL (works on iOS Safari)
- Bulk download uses hidden iframes instead of fetch+blob
- Fix COI gate: getCOIStatus returns null (not undefined) when undeclared,
  so `!== undefined` was always true — changed to `!= null`

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
This commit is contained in:
Matt
2026-02-18 14:56:09 +01:00
parent 8d28104d51
commit 9c19661400
4 changed files with 38 additions and 56 deletions

View File

@@ -84,11 +84,17 @@ export async function getPresignedUrl(
bucket: string,
objectKey: string,
method: 'GET' | 'PUT' = 'GET',
expirySeconds: number = 900 // 15 minutes default
expirySeconds: number = 900, // 15 minutes default
options?: { downloadFileName?: string }
): Promise<string> {
let url: string
if (method === 'GET') {
url = await minio.presignedGetObject(bucket, objectKey, expirySeconds)
// If downloadFileName is set, include Content-Disposition: attachment header
// so the browser triggers a native download (works on iOS Safari, all browsers)
const respHeaders = options?.downloadFileName
? { 'response-content-disposition': `attachment; filename="${options.downloadFileName}"` }
: undefined
url = await minio.presignedGetObject(bucket, objectKey, expirySeconds, respHeaders)
} else {
url = await minio.presignedPutObject(bucket, objectKey, expirySeconds)
}