Skip to content

Commit 1628ffe

Browse files
TheodoreSpeaksTheodore Li
andauthored
fix(download-file): render correct file download link for mothership (#3522)
* fix(download-file): render correct file download link for mothership * Fix uunecessary call * Use simple strip instead of db lookup and moving behavior * Make regex strip more strict --------- Co-authored-by: Theodore Li <theo@sim.ai>
1 parent 95efa50 commit 1628ffe

File tree

3 files changed

+19
-8
lines changed

3 files changed

+19
-8
lines changed

apps/sim/app/api/files/serve/[...path]/route.ts

Lines changed: 17 additions & 8 deletions
Original file line numberDiff line numberDiff line change
@@ -18,6 +18,12 @@ import {
1818

1919
const logger = createLogger('FilesServeAPI')
2020

21+
const STORAGE_KEY_PREFIX_RE = /^\d{13}-[a-z0-9]{7}-/
22+
23+
function stripStorageKeyPrefix(segment: string): string {
24+
return STORAGE_KEY_PREFIX_RE.test(segment) ? segment.replace(STORAGE_KEY_PREFIX_RE, '') : segment
25+
}
26+
2127
export async function GET(
2228
request: NextRequest,
2329
{ params }: { params: Promise<{ path: string[] }> }
@@ -103,14 +109,16 @@ async function handleLocalFile(filename: string, userId: string): Promise<NextRe
103109
}
104110

105111
const fileBuffer = await readFile(filePath)
106-
const contentType = getContentType(filename)
112+
const segment = filename.split('/').pop() || filename
113+
const displayName = stripStorageKeyPrefix(segment)
114+
const contentType = getContentType(displayName)
107115

108116
logger.info('Local file served', { userId, filename, size: fileBuffer.length })
109117

110118
return createFileResponse({
111119
buffer: fileBuffer,
112120
contentType,
113-
filename,
121+
filename: displayName,
114122
cacheControl: contextParam === 'workspace' ? 'private, no-cache, must-revalidate' : undefined,
115123
})
116124
} catch (error) {
@@ -159,8 +167,9 @@ async function handleCloudProxy(
159167
})
160168
}
161169

162-
const originalFilename = cloudKey.split('/').pop() || 'download'
163-
const contentType = getContentType(originalFilename)
170+
const segment = cloudKey.split('/').pop() || 'download'
171+
const displayName = stripStorageKeyPrefix(segment)
172+
const contentType = getContentType(displayName)
164173

165174
logger.info('Cloud file served', {
166175
userId,
@@ -172,7 +181,7 @@ async function handleCloudProxy(
172181
return createFileResponse({
173182
buffer: fileBuffer,
174183
contentType,
175-
filename: originalFilename,
184+
filename: displayName,
176185
cacheControl: context === 'workspace' ? 'private, no-cache, must-revalidate' : undefined,
177186
})
178187
} catch (error) {
@@ -197,8 +206,8 @@ async function handleCloudProxyPublic(
197206
})
198207
}
199208

200-
const originalFilename = cloudKey.split('/').pop() || 'download'
201-
const contentType = getContentType(originalFilename)
209+
const filename = cloudKey.split('/').pop() || 'download'
210+
const contentType = getContentType(filename)
202211

203212
logger.info('Public cloud file served', {
204213
key: cloudKey,
@@ -209,7 +218,7 @@ async function handleCloudProxyPublic(
209218
return createFileResponse({
210219
buffer: fileBuffer,
211220
contentType,
212-
filename: originalFilename,
221+
filename,
213222
})
214223
} catch (error) {
215224
logger.error('Error serving public cloud file:', error)

apps/sim/lib/copilot/orchestrator/sse/handlers/tool-execution.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -179,6 +179,7 @@ async function maybeWriteOutputToFile(
179179
fileId: uploaded.id,
180180
fileName,
181181
size: buffer.length,
182+
downloadUrl: uploaded.url,
182183
},
183184
}
184185
} catch (err) {

apps/sim/lib/copilot/tools/server/files/workspace-file.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -83,6 +83,7 @@ export const workspaceFileServerTool: BaseServerTool<WorkspaceFileArgs, Workspac
8383
name: result.name,
8484
contentType,
8585
size: fileBuffer.length,
86+
downloadUrl: result.url,
8687
},
8788
}
8889
}

0 commit comments

Comments
 (0)