Skip to content

fix: stream custom map imports from disk when the file supports it#197

Open
gmaclennan wants to merge 1 commit into
mainfrom
fix/stream-map-import-upload
Open

fix: stream custom map imports from disk when the file supports it#197
gmaclennan wants to merge 1 commit into
mainfrom
fix/stream-map-import-upload

Conversation

@gmaclennan

Copy link
Copy Markdown
Member

Problem

useImportCustomMapFile() uploads the map file with fetch. On React Native the injected expo/fetch implementation reads the whole request body into memory before sending (normalizeBodyInitAsync converts any Blob-shaped body, including an expo-file-system File, to a Uint8Array — still the case in SDK 56). Large SMP files can exhaust memory, which is why comapeo-mobile currently carries a patch to expo/fetch adding native file streaming. That patch is Android-only and has to be rebased on every SDK upgrade.

Solution

expo-file-system's File.upload() streams the file from disk on both platforms (OkHttp RequestBody streaming from an InputStream on Android, URLSession.uploadTask(fromFile:) on iOS), so we can use it instead of fetch when it's available.

This adds an uploadFile method to the internal map server API which duck-types the file: if it has an upload method it is called with the resolved URL (httpMethod: 'PUT', and sessionType: 'foreground', since an iOS background session can't reach the in-process map server across app suspension); otherwise it falls back to the existing fetch PUT, so web and electron are unaffected (browser fetch already streams File bodies from disk). The mutation keeps its existing contract: it resolves with a Response and rejects with an HTTPError (error details parsed from a JSON body when available) on non-2xx responses.

With this, comapeo-mobile can drop its expo/fetch patch entirely.

Importing a custom map via useImportCustomMapFile uploaded the file with
fetch, which on React Native (expo/fetch) reads the whole request body
into memory before sending - large SMP files could exhaust memory.

Add an uploadFile method to the map server API that uses the file's own
upload method when it has one (e.g. expo-file-system's File.upload(),
which streams the file from disk on both Android and iOS) and falls back
to the existing fetch PUT otherwise, so web and electron are unaffected.
Non-2xx upload responses are normalized to the same HTTPError thrown by
the fetch path.
@achou11
achou11 self-requested a review July 23, 2026 17:04

@achou11 achou11 left a comment

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Couple of non-blocking comments but otherwise lgtm

Comment thread src/contexts/MapServer.ts
// import function we accept an object with the compatible properties and
// methods, and for the expo File, which can represent a file that does not yet
// exists, we type the `exists` property so that we can check that.
export type CompatFile = Omit<File, 'lastModified' | 'webkitRelativePath'>

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

not necessary to export this type right now

Suggested change
export type CompatFile = Omit<File, 'lastModified' | 'webkitRelativePath'>
type CompatFile = Omit<File, 'lastModified' | 'webkitRelativePath'>

Comment thread src/contexts/MapServer.ts
}

type ExpoFileWithUpload = ExpoFileDuckType & {
upload(

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

Comment thread src/contexts/MapServer.ts
Comment on lines +42 to +46
options?: {
headers?: Record<string, string>
httpMethod?: string
sessionType?: 'background' | 'foreground'
},

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

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

just checking: none of the other options are relevant to us?

https://docs.expo.dev/versions/v56.0.0/sdk/filesystem/#uploadoptions

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