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

[expo-file-system][next] Add download function. #30841

Merged
merged 19 commits into from
Aug 30, 2024
Merged

Conversation

aleqsio
Copy link
Contributor

@aleqsio aleqsio commented Aug 6, 2024

Why

We allow downloading files and immediately getting a File instance to read the downloaded file.

How

Added a module-level download function. We accept both target files and directories (we try to get the filename from correct headers)

Test Plan

Added test cases.

Checklist

@expo-bot expo-bot added the bot: suggestions ExpoBot has some suggestions label Aug 6, 2024
@expo-bot
Copy link
Collaborator

expo-bot commented Aug 6, 2024

The Pull Request introduced fingerprint changes against the base commit: 9bba2fe

Fingerprint diff
[
  {
    "op": "changed",
    "source": {
      "type": "dir",
      "filePath": "../../packages/expo-file-system/android",
      "reasons": [
        "expoAutolinkingAndroid"
      ],
      "hash": "d82cffb9b98d8fa3d17b1504eb3cf5bff7d9e516"
    }
  },
  {
    "op": "changed",
    "source": {
      "type": "dir",
      "filePath": "../../packages/expo-file-system/ios",
      "reasons": [
        "expoAutolinkingIos"
      ],
      "hash": "92f1b0f73ad303ed8a7c63a0e341b735ef87a8cf"
    }
  },
  {
    "op": "changed",
    "source": {
      "type": "dir",
      "filePath": "../../packages/expo-modules-core",
      "reasons": [
        "expoAutolinkingIos",
        "expoAutolinkingAndroid"
      ],
      "hash": "a4c3c84f7eff58977cc1662c607eea45b6ba7f8f"
    }
  }
]

Generated by PR labeler 🤖

@aleqsio aleqsio force-pushed the @aleqsio/add-download branch from 2b40b10 to a23ffff Compare August 22, 2024 12:45
@expo-bot expo-bot added bot: passed checks ExpoBot has nothing to complain about and removed bot: suggestions ExpoBot has some suggestions labels Aug 22, 2024
@aleqsio aleqsio marked this pull request as ready for review August 22, 2024 13:27
@aleqsio aleqsio requested a review from lukmccall August 22, 2024 13:28
@@ -12,3 +14,9 @@ internal class MoveDirectoryToFileException: Exception {
"Unable to move a directory to a file"
}
}

internal class UnableToDownloadException: GenericException<String> {
Copy link
Contributor Author

Choose a reason for hiding this comment

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

Is this OK, or should we make several reasons (no response, invalid response code (300/400), other)?

Copy link
Member

Choose a reason for hiding this comment

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

We could consider that in the future, but for now I think we don't have a very good mechanism for handling exceptions on the JS side – we should have our own Error class that can contain some custom data (like the response code) etc. and works well with error chaining

@aleqsio aleqsio requested a review from lukmccall August 22, 2024 14:02
@expo-bot expo-bot added bot: suggestions ExpoBot has some suggestions and removed bot: passed checks ExpoBot has nothing to complain about labels Aug 22, 2024
Copy link
Contributor

@lukmccall lukmccall left a comment

Choose a reason for hiding this comment

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

Android part looks good!

@expo-bot expo-bot added bot: passed checks ExpoBot has nothing to complain about and removed bot: suggestions ExpoBot has some suggestions labels Aug 22, 2024
@@ -6,6 +6,40 @@ public final class FileSystemNextModule: Module {
public func definition() -> ModuleDefinition {
Name("FileSystemNext")

AsyncFunction("download") { (url: URL, to: FileSystemPath, promise: Promise) in
let downloadTask = URLSession.shared.downloadTask(with: url) { urlOrNil, responseOrNil, errorOrNil in
Copy link
Member

Choose a reason for hiding this comment

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

Would be great if there is an async/await version of that function

Copy link
Member

Choose a reason for hiding this comment

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

This is not resolved 😅 But I think it might be hard to make an async version of downloadTask(with:) as opposed to the already existing download(from:). The latter doesn't seem to support downloading when the app is suspended though.

packages/expo-file-system/src/next/index.ts Outdated Show resolved Hide resolved
const directory = new Directory(testDirectory);
const output = await download(url, directory);
const file = new File(
testDirectory + (Platform.OS === 'android' ? 'jpeg.jpg' : 'jpeg.jpeg')
Copy link
Member

Choose a reason for hiding this comment

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

Can't we use the same extension on all platforms?

Copy link
Contributor Author

@aleqsio aleqsio Aug 23, 2024

Choose a reason for hiding this comment

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

We rely on OS functions to get a filename based on URL headers – I don't want to write my own now, but can look into that a bit more in the future.
https://developer.android.com/reference/android/webkit/URLUtil#guessFileName(java.lang.String,%20java.lang.String,%20java.lang.String)

@aleqsio aleqsio requested a review from tsapeta August 23, 2024 16:34
@aleqsio aleqsio force-pushed the @aleqsio/add-download branch from 8b2d4a5 to a64b846 Compare August 29, 2024 10:05
@@ -12,3 +14,9 @@ internal class MoveDirectoryToFileException: Exception {
"Unable to move a directory to a file"
}
}

internal class UnableToDownloadException: GenericException<String> {
Copy link
Member

Choose a reason for hiding this comment

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

We could consider that in the future, but for now I think we don't have a very good mechanism for handling exceptions on the JS side – we should have our own Error class that can contain some custom data (like the response code) etc. and works well with error chaining

@@ -6,6 +6,40 @@ public final class FileSystemNextModule: Module {
public func definition() -> ModuleDefinition {
Name("FileSystemNext")

AsyncFunction("download") { (url: URL, to: FileSystemPath, promise: Promise) in
let downloadTask = URLSession.shared.downloadTask(with: url) { urlOrNil, responseOrNil, errorOrNil in
Copy link
Member

Choose a reason for hiding this comment

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

This is not resolved 😅 But I think it might be hard to make an async version of downloadTask(with:) as opposed to the already existing download(from:). The latter doesn't seem to support downloading when the app is suspended though.

@@ -6,6 +6,40 @@ public final class FileSystemNextModule: Module {
public func definition() -> ModuleDefinition {
Name("FileSystemNext")

AsyncFunction("download") { (url: URL, to: FileSystemPath, promise: Promise) in
Copy link
Member

Choose a reason for hiding this comment

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

To be honest I think this should return a shared object (like the download task) that you can then pause/resume/cancel/listen to progress. It might be better to call it downloadFile(Async?) (since it returns a File instance) and then we can introduce more powerful download/downloadTask in the future.

@aleqsio aleqsio force-pushed the @aleqsio/add-download branch from 9276c7e to 3401835 Compare August 29, 2024 16:17
@aleqsio aleqsio merged commit bab7aec into main Aug 30, 2024
12 of 13 checks passed
@aleqsio aleqsio deleted the @aleqsio/add-download branch August 30, 2024 09:38
behenate pushed a commit that referenced this pull request Sep 30, 2024
# Why

We allow downloading files and immediately getting a `File` instance to
read the downloaded file.

# How

Added a module-level `download` function. We accept both target files
and directories (we try to get the filename from correct headers)

# Test Plan

Added test cases.

# Checklist

<!--
Please check the appropriate items below if they apply to your diff.
This is required for changes to Expo modules.
-->

- [ ] Documentation is up to date to reflect these changes (eg:
https://docs.expo.dev and README.md).
- [ ] Conforms with the [Documentation Writing Style
Guide](https://github.com/expo/expo/blob/main/guides/Expo%20Documentation%20Writing%20Style%20Guide.md)
- [ ] This diff will work correctly for `npx expo prebuild` & EAS Build
(eg: updated a module plugin).

---------

Co-authored-by: Expo Bot <[email protected]>
Co-authored-by: Łukasz Kosmaty <[email protected]>
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
bot: fingerprint changed bot: passed checks ExpoBot has nothing to complain about
Projects
None yet
Development

Successfully merging this pull request may close these issues.

4 participants