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

@@ -15,6 +15,8 @@ export const fileRouter = router({
z.object({
bucket: z.string(),
objectKey: z.string(),
forDownload: z.boolean().optional(),
fileName: z.string().optional(),
})
)
.query(async ({ ctx, input }) => {
@@ -109,7 +111,9 @@ export const fileRouter = router({
}
}
const url = await getPresignedUrl(input.bucket, input.objectKey, 'GET', 900) // 15 min
const url = await getPresignedUrl(input.bucket, input.objectKey, 'GET', 900,
input.forDownload ? { downloadFileName: input.fileName || input.objectKey.split('/').pop() || 'download' } : undefined
) // 15 min
// Log file access
await logAudit({
@@ -699,7 +703,9 @@ export const fileRouter = router({
// Generate signed URLs for each file
const results = await Promise.all(
files.map(async (file) => {
const downloadUrl = await getPresignedUrl(file.bucket, file.objectKey, 'GET', 900)
const downloadUrl = await getPresignedUrl(file.bucket, file.objectKey, 'GET', 900,
{ downloadFileName: file.fileName }
)
return {
fileId: file.id,
fileName: file.fileName,