Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Add an endpoint to download a file #818

Merged
merged 6 commits into from
Nov 4, 2023
Merged

Add an endpoint to download a file #818

merged 6 commits into from
Nov 4, 2023

Conversation

a3957273
Copy link
Member

No description provided.

@@ -31,3 +31,21 @@ export async function putObjectStream(bucket: string, key: string, body: Readabl
fileSize,
}
}

export async function getObjectStream(bucket: string, key: string, range?: { start: number; end: number }) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests for this method?

@@ -31,3 +31,21 @@ export async function putObjectStream(bucket: string, key: string, body: Readabl
fileSize,
}
}

export async function getObjectStream(bucket: string, key: string, range?: { start: number; end: number }) {
const client = await getS3Client()
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do we need to create a new S3 Client for every S3 request?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Our S3 credentials expire on some platforms relatively frequently. Tracking whether the current S3 client has expired and replacing it seems too complex for a function that's likely to only get called a few hundred - thousand times a day.

export const getDownloadFileSchema = z.object({
params: z.object({
modelId: z.string({
required_error: 'Must specify model id as param',
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

The standard Zod error here would be sufficient?

res.set('Content-Type', file.mime)
res.set('Cache-Control', 'public, max-age=604800, immutable')

if (req.headers.range) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Do this first before logic for response?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Range requests will include the same headers (Content-Type, Cache-Control and Content-Disposition) seen above. The idea behind placing it here is that when we do support it you can just write the implementation in here and not need to change anything else.

I could move the error up (rule: do error checking first), but it feels like a waste for now.

}

// The AWS library doesn't seem to properly type 'Body' as being pipeable?
;(stream.Body as any).pipe(res)
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Can you raise this issue on their repo?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Existing issue here: aws/aws-sdk-js-v3#4720

Also narrowed type to stream.Readable from any. Issue seems to be that the AWS client is isomorphic, but you only get streams on Node so they're loosely typed.


// The AWS library doesn't seem to properly type 'Body' as being pipeable?
;(stream.Body as any).pipe(res)
},
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Am I missing something, where is the method's return statement?

Copy link
Member Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

We don't need to return anything. The pipe will close the response stream when the Body is done being streamed to the user.

@@ -37,6 +37,18 @@ export async function uploadFile(user: UserDoc, modelId: string, name: string, m
return file
}

export async function downloadFile(user: UserDoc, fileId: string, range?: { start: number; end: number }) {
Copy link
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Tests?

@a3957273 a3957273 merged commit 18df916 into main Nov 4, 2023
15 checks passed
@a3957273 a3957273 deleted the feature/download-file branch November 4, 2023 00:10
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

Successfully merging this pull request may close these issues.

2 participants