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

[Request]: Use the XFile.name as the shared file name #1548

Closed
josephelliot-wk opened this issue Feb 16, 2023 · 25 comments
Closed

[Request]: Use the XFile.name as the shared file name #1548

josephelliot-wk opened this issue Feb 16, 2023 · 25 comments
Labels
enhancement New feature or request triage

Comments

@josephelliot-wk
Copy link

Plugin

share_plus

Use case

Our app lets users open files (usually PDFs), and some of these files have special characters that don't play nicely with temp-file paths.

For example, My First / Last File.pdf causes an error when writing to temp storage.

To combat this, you need to sanitize the file name to play nicely with the native file system. But, when share_plus shares this file (via Share.shareXFiles), it uses the file name from the path instead of the XFile's name property.

According to the XFile documentation, name is intended to be used for this exact scenario.

Proposal

I propose that the function Share.shareXFiles utilizes XFile.name for the file name, if available. If not available, then default to the path file name.

@josephelliot-wk josephelliot-wk added enhancement New feature or request triage labels Feb 16, 2023
@lukasnevosad
Copy link

I second to this. I am creating the file with XFile.fromData() and this is the only option for me to have a user friendly file name.

@intraector
Copy link

Same here. Getting image from web without any file extension causes the share with .BIN

@Boucaa
Copy link

Boucaa commented May 30, 2023

Is there at least any workaround for this currently?

@wildsurfer
Copy link

same issue

@DieGlueckswurst
Copy link

Any updates on this ?

@IshanBaliyan
Copy link

Same here, seems like the bug still isnt fixed

@intraector
Copy link

Please fix this

@falerr
Copy link

falerr commented Dec 12, 2023

Any way to change the name using XFile.fromdata() ? Since name: doesn't work.

@adimshev
Copy link

any updates?

@erighet
Copy link

erighet commented Feb 12, 2024

Same request from me, now Share.shareXFiles causes files to have uuid like file name

@bytepoets-jhe
Copy link

Same problem here

@nidalshehab
Copy link

it would be better to use file instead of XFile.fromData, this way you can name the file and delete it after sharing to keep the temporary directory clean, here is a work around:

Future<File> writeFile(List<int>? excel, String fileName) async {
    final directory = await getApplicationDocumentsDirectory();
    final path = directory.path;
    final file = File('$path/$fileName');
    return file.writeAsBytes(excel!);
  }

if it's an exported excel file:

List<int>? excel =  exportToExcel(); 
 String fileName = 'example.xlsx'; // Desired file name
 File file = await writeFile(excel, fileName);
 await Share.shareXFiles([XFile(file.path)]);

@LBYPatrick
Copy link
Contributor

LBYPatrick commented Mar 9, 2024

Same here! And I don't like the idea of writing file into persistent storage then read from it...Why bother the round trip? BTW XFile works flawlessly on macOS and iPhone for some reason but not on Android and Chrome?!

@miquelbeltran

This comment was marked as off-topic.

@LBYPatrick
Copy link
Contributor

LBYPatrick commented Mar 10, 2024

OK, I have removed that piece of the comment. With that said, I believe the Android implementation for XFile.fromData should also respect the filename and extension supplied by the user instead of generating a UUID-like filename along with a "reconstructed" extension that, If I have to guess, is based on the interpreted result of the MIME type of the real filename. This is technically fine, but xxxxx.jpeg will be matched to image/jpe by the mime package and the generated filename might have an extension of .jpe, which has all kinds of compatibility issues with the platforms that were designed to handle .jpeg and .jpg.

In this case, if the shared file on Android is of extension .jpe, then in some Android Distributions (not sure about Google Pixel, but did run into this issue on Xiaomi's MIUI), image / SMS apps might fail to recognize that it's an image and thus will not show up in the share menu.

When I got time, I will definitely open a PR to address this issue!

I think I have identified the issue and might be able to fix it by modify these lines to achieve the effect the OP (and us) wants!

@miquelbeltran
Copy link
Member

xxxxx.jpeg will be matched to image/jpe by the mime package

I see, this is reported here: dart-lang/mime#55 at least the PR is getting some movement, I have subscribed to updates.

If anyone tries to do a dependency_override to the fixed branch, let me know how it went!

Once mime is updated, we will update the dependency too.

@LBYPatrick
Copy link
Contributor

LBYPatrick commented Mar 12, 2024

Ah, I mean I came up with a workaround that respects the extension from user's filename and then fallback to the MIME way in case it fails.

By the way, may I ask why was the filename discarded and UUID was used instead?Is it for collision prevention or ASCII-compliance because of some legacy issues that I am not aware of?

@miquelbeltran
Copy link
Member

By the way, may I ask why was the filename discarded and UUID was used instead?Is it for collision prevention or ASCII-compliance because of some legacy issues that I am not aware of?

I don't remember, sorry. Maybe the git log or the original pr have a clue.

@LBYPatrick
Copy link
Contributor

LBYPatrick commented Mar 12, 2024

haha no worries! I am trying to digest #1188 to see if I can get the full picture of the original issue. But based on my test against a real android phone (namely image_picker that yields files as XFiles) using XFile the intent URLs do not contain regular filenames but rather something like content://xxx, which requires us to use path_provider to deal with it, given that we know which platform the user is running our code on...

@miquelbeltran
Copy link
Member

Should be closed by #2713 pending to be released.

Thanks a lot @LBYPatrick for the contribution!

@LBYPatrick
Copy link
Contributor

LBYPatrick commented Mar 17, 2024

...Haha you are welcome! Though, I have noticed that our test cases for flutter test do not contain proper tests for simulating the case where we intentionally tamper the path but set XFile.name and XFile.mimeType properly (Which is what image_picker would sometimes do in Android). In other words, my code might not be well covered by the test cases unless we run the CI integration tests upon opening PRs...I will follow up with another PR to see if I can pull it off!

@LBYPatrick
Copy link
Contributor

LBYPatrick commented Mar 17, 2024

Unfortunately I am not familiar with the testing pipeline so I am having a hard time writing such test. With that said, I noticed that getTemporaryDirectory() is not available at all under the test environment, so we cannot direct test it with flutter test but only with the integration tests:

image

I thought about exposing the tempRoot variable for us to dictate where temporary files should go solely for testing purposes, but doing so will also expose this variable to the users, which I don't know if this will confuse the users or allow them to do things we do not expect them to (i.e. saving temporary files to some invalid path). Or do you think there's another way we can simulate this case and somehow extract the intermediate outputs of _getFile or _getFiles? They are package-private methods and are guarded behind the user-facing share methods, and I am just...not sure about it.

And here's my half-baked test code:

 test(
      'simulate the edge case where XFile.path is not set but XFile.name is (usually from XFile.fromData)',
      () async {
    await withFile("tempfile-83649f.png", (File fd) async {
      final bytes = await fd.readAsBytes();

      //This file may not have path in it but has XFile.name
      final XFile badFile = XFile.fromData(bytes, name: "tempfile-83649f.png");

      final res = await sharePlatform.shareXFiles([badFile]);

      verify(mockChannel.invokeMethod('shareFilesWithResult', <String, dynamic>{
        'paths': ["*/tempfile-83649f.png"],
        'mimeTypes': ['image/png'],
      }));
    });

@ibrahimtelman
Copy link

There is an issue with the raw data usage. The Cross file package doesn't return the name parameter when using 'XFile.fromData'. Because of that, this issue should be open.

@Core121
Copy link

Core121 commented May 15, 2024

Agreed with @ibrahimtelman that raw data names do not work still

@Nico04
Copy link

Nico04 commented May 23, 2024

Same issue here, name parameter is ignored when using 'XFile.fromData'

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
enhancement New feature or request triage
Projects
None yet
Development

No branches or pull requests