Skip to content

Commit d428bbd

Browse files
authored
Merge pull request #886 from marksgraham/image-out2
Generate signed URLs for images
2 parents 741eb5c + 53e9996 commit d428bbd

File tree

1 file changed

+28
-7
lines changed

1 file changed

+28
-7
lines changed

functions/src/utils/storage.ts

Lines changed: 28 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -6,7 +6,9 @@ import {generateId} from '@deliberation-lab/utils';
66
* @param base64Data The base64 encoded image string.
77
* @param mimeType The MIME type of the image.
88
* @param prefix A prefix for the file name in the bucket.
9-
* @returns The public URL of the uploaded image.
9+
* @returns A URL for the uploaded image.
10+
* - In production: signed URL valid for 7 days
11+
* - In emulator: public URL (emulator can't sign)
1012
*/
1113
export async function uploadBase64ImageToGCS(
1214
base64Data: string,
@@ -20,11 +22,30 @@ export async function uploadBase64ImageToGCS(
2022

2123
const buffer = Buffer.from(base64Data, 'base64');
2224

23-
await file.save(buffer, {
24-
metadata: {
25-
contentType: mimeType,
26-
},
27-
});
25+
const isEmulator = process.env.FUNCTIONS_EMULATOR === 'true';
2826

29-
return file.publicUrl();
27+
if (isEmulator) {
28+
// Emulator: save and return public URL (emulator can't sign URLs)
29+
await file.save(buffer, {
30+
metadata: {
31+
contentType: mimeType,
32+
},
33+
public: true,
34+
});
35+
return file.publicUrl();
36+
} else {
37+
// Production: save and return signed URL (works regardless of bucket ACL settings)
38+
await file.save(buffer, {
39+
metadata: {
40+
contentType: mimeType,
41+
},
42+
});
43+
44+
const [signedUrl] = await file.getSignedUrl({
45+
action: 'read',
46+
expires: Date.now() + 7 * 24 * 60 * 60 * 1000, // 7 days
47+
});
48+
49+
return signedUrl;
50+
}
3051
}

0 commit comments

Comments
 (0)