miguelpruivo / flutter_file_picker

File picker plugin for Flutter, compatible with mobile (iOS & Android), Web, Desktop (Mac, Linux, Windows) platforms with Flutter Go support.
MIT License
1.33k stars 664 forks source link

After I picked a file, the current working directory will be modified. #804

Closed sunjhtrustmobi closed 2 years ago

sunjhtrustmobi commented 3 years ago

Describe the bug After everytime I picked a file, and I go to visit any files under my project directory by File(path), I will failed. The system will inform me that it can't find the designated path. Because the file_picker has modified the uri of my project, which caused I can't visit files just by realitived path. So I wonder if there any ways to make it not to modify the path or use a variable to get the value of the path.

Platform [√] Flutter (Channel stable, 2.0.4, on Microsoft Windows [Version 10.0.19042.1165], locale zh-CN) [√] Android toolchain - develop for Android devices (Android SDK version 30.0.1) [√] Chrome - develop for the web [√] Visual Studio - develop for Windows (Visual Studio Community 2019 16.9.4)
[√] Android Studio (version 3.0) [√] Android Studio (version 3.6)

Platform OS version Microsoft Windows [Version 10.0.19042.1165], locale zh-CN How are you picking? Pick any picture , and it hanppens.

Details to reproduce the issue Provide all the details to reproduce the issue.

Error Log This error occured after I picked a picture. My program can't find the correct path of the file because I used realitive path. So I wonder why the FIle_Picker will modify the working directory of the program. [ERROR:flutter/lib/ui/ui_dart_state.cc(186)] Unhandled Exception: Exception: FileSystemException: Cannot open file, path = 'E:\AndroidStdioProject\Flutter_SecEMS_master\flutter_secemsassets/thumb/img_1629534237605.jpg' (OS Error: 系统找不到指定的路径。 , errno = 3)

0 _File.throwIfError (dart:io/file_impl.dart:635:7)

1 _File.openSync (dart:io/file_impl.dart:479:5)

2 _File.writeAsBytesSync (dart:io/file_impl.dart:604:31)

3 Luban._large2SmallCompressImage

package:flutter_luban/src/flutter_luban.dart:229

4 Luban._large2SmallCompressImage

package:flutter_luban/src/flutter_luban.dart:220

5 Luban._lubanCompress

package:flutter_luban/src/flutter_luban.dart:185

Screenshots and/or video 系统找不到指定路径

Flutter Version details [√] Flutter (Channel stable, 2.0.4, on Microsoft Windows [Version 10.0.19042.1165], locale zh-CN) • Flutter version 2.0.4 at E:\flutter_windows_2.0.4\flutter • Framework revision b1395592de (5 months ago), 2021-04-01 14:25:01 -0700 • Engine revision 2dce47073a • Dart version 2.12.2 • Pub download mirror https://pub.flutter-io.cn • Flutter download mirror https://storage.flutter-io.cn

[√] Android toolchain - develop for Android devices (Android SDK version 30.0.1) • Android SDK at F:\sdk • Platform android-30, build-tools 30.0.1 • ANDROID_HOME = F:\sdk\sdk • Java binary at: F:\AndroidStudio\Android Studio2\jre\bin\java • Java version OpenJDK Runtime Environment (build 1.8.0_212-release-1586-b04) • All Android licenses accepted.

[√] Chrome - develop for the web • Chrome at C:\Program Files\Google\Chrome\Application\chrome.exe

[√] Visual Studio - develop for Windows (Visual Studio Community 2019 16.9.4) • Visual Studio at E:\Visual Studio • Visual Studio Community 2019 version 16.9.31205.134 • Windows 10 SDK version 10.0.19041.0

[√] Android Studio (version 3.0) • Android Studio at F:\AndroidStudio\Android Studio1 • Flutter plugin can be installed from: https://plugins.jetbrains.com/plugin/9212-flutter • Dart plugin can be installed from: https://plugins.jetbrains.com/plugin/6351-dart • Java version OpenJDK Runtime Environment (build 1.8.0_112-release-b06)

[√] Android Studio (version 3.6) • Android Studio at F:\AndroidStudio\Android Studio2 • Flutter plugin version 49.0.1 • Dart plugin version 192.8052 • Java version OpenJDK Runtime Environment (build 1.8.0_212-release-1586-b04)

[√] Connected device (3 available) • Windows (desktop) • windows • windows-x64 • Microsoft Windows [Version 10.0.19042.1165] • Chrome (web) • chrome • web-javascript • Google Chrome 92.0.4515.159 • Edge (web) • edge • web-javascript • Microsoft Edge 92.0.902.73

miguelpruivo commented 3 years ago

Hi, I really don't understand what is this issue about.

sunjhtrustmobi commented 3 years ago

Hi, I really don't understand what is this issue about.

When I use the file system to visit 'assets/pictures/image.jpg' in flutter, the system will add the default path before my path, like 'C: flutter_project/myProject'. But after I picked a file with this plugin, the default path will be changed to the path of file I just picked. Then I can't visit 'assets/pictures/image.jpg' like before. So I wonder if you could not modify the default path when pick files or reset it after modifing?

miguelpruivo commented 3 years ago

When files are picked they are cached internally in the app’s temporary directory. You can manually move/rename/delete to wherever you want, it’s up to the dev. But as a default, it makes sense to stay in the temporary directory, so the system can purge it if space is required for something else.

labaxter commented 3 years ago

@miguelpruivo : what I would call your "policy" (articulated in the previous comment) I suspect relates to a problem which is likely to lead me away from using file_picker. This is a "safe' policy, but the problem is that it does not give the developer or user control.

When I pick a file in an External Storage (usb storage device), the actual (mangled) path to the folder is shown in the debug statements, but when the path is displayed in the UI, it is just '/'. This is not useful to me, if I want to allow a user to select a folder on a usb stick (external storage) that contains an mp3 hierachy, and I want to then provide that folder to a music player that I want to play all the music files in that folder, it does not work.

It would be very helpful if you would provide a mechanism to override this policy (which I am fine with being the safe default), and allow the return of the literal absolute path. Let the developer (and the user) decide!

miguelpruivo commented 3 years ago

@labaxter you can access the paths (directories) if you want to, just not the protected ones (which Downloads directory is one of those, hence the reason it returns /).

Regarding the absolute paths, that's not possible at all since SDK 30, it's blocked from Android API. Files should be handled through its URI which aren't util for Flutter side, since you can't open a File descriptor with it.

You can read about it here and learn more about it here.

sunjhtrustmobi commented 3 years ago

When files are picked they are cached internally in the app’s temporary directory. You can manually move/rename/delete to wherever you want, it’s up to the dev. But as a default, it makes sense to stay in the temporary directory, so the system can purge it if space is required for something else.

I mean that could you use another variable to return the path and set the current path to default. In that case, it won't affect others when visit 'assets/pictures/image.jpg'.

labaxter commented 3 years ago

@miguelpruivo I total agree with @sunjhtrustmobi's comment. This would maintain backwards compatibility, AND would provide useful functionality. Perhaps you could call the variable "chosenPath" This make this usable for my purposes. I can always open a URI against this path.

miguelpruivo commented 3 years ago

@labaxter what would be your solution then? Exposing the native URI?

labaxter commented 3 years ago

@miguelpruivo Yes. I was actually thinking about cloning your package, to do just that, but I wasn't going to do it, until I explored some other options. This would save me time, which is the point of packages.

FWIW: I want this path (which my app would then request permanent permission to access) so that I can pass it to a background music playing task, using the BLoC pattern (https://pub.dev/packages/flutter_bloc).

The background task (or service) would play all the files (one at a time) in the chosen path until all have been played, or the user stops it via the UI. (None of the MANY existing music players I have tried do this allowing selection by file system hierarchy or from external storage which is what I require. The "FX File Explorer" app will browse external storage and start playing music, but it quits playing when the screen goes to sleep. There is no way I am going to be able to copy 250GB of mp3s in my music collection from the USB stick on to device local storage. Hence my requirement to access the files in place on the external storage (read only).

Thanks for entertaining this thought. I understand that in fact on native Linux, windows, and maybe MacOS, the "chosenPath" (or whatever you chose to call it) may in fact be the same as the current Path returned. This solution would give the user's application the choice of how to use the information provided by the user, and, IMO, would be a valuable improvement to file_picker.

miguelpruivo commented 2 years ago

The identifier is now available with 4.2.0.

Let me know if it suits your needs.

sunjhtrustmobi commented 2 years ago

I have tried recently, but find it doesn't work. The path still changed when I get the current path from Path.current.

labaxter commented 2 years ago

It may be that @sunjhtrustmobi is still trying to access the original path, and not the new identifier. I understand that the behavior of path can not be changed without breaking backwards compatibility. But, can you provide a code sample that tests this or shows how it is used to get the 'path' the user selected? Can you show how one references this 'identifier' in a sample application?

miguelpruivo commented 2 years ago

@labaxter that is only useful if you handle files through native URIs (using platform channels), that’s why cached files — and absolute paths — are required by Flutter (and Dart) to access the native file descriptors.

Tokenyet commented 2 years ago

I must say, change current directory is really a bad idea for some circumstances. I've used the wrapper package file. That is independent from dart:io's Directory.current. But this package change both current directory to the file location that we picked. It not only mess up dart:io but aslo file.

This is my experience of using this package, hope there is an optional paramenter such as restoreCurrentDir to restore back what It was:

  Future<List<String>> pickFile() async {
    FilePickerResult? result = await _picker.pickFiles(
      type: FileType.custom,
      allowedExtensions: ['png'],
      restoreCurrentDir: ture
    );
    ...
  }

Edit Seems that the behavior is different on different platform. I use Windows mainly, so the description is for Windows, but when I test Linux, It won't change current directory. After searching the source code, only Windows change the current directory on Desktop, that's inconsistent with Linux and Macos. I suggest that we use OFN_NOCHANGEDIR to make desktop more consistent.

arthas1888 commented 2 years ago

any updates with this issue?