Flutter错误:“PathNotFoundException: 无法打开文件,路径”

huangapple go评论79阅读模式
英文:

Flutter error "PathNotFoundException: Cannot open file, path "

问题

I built an app to upload attachments to Firebase Storage, with the URL saved in Firestore. The upload part works nicely. I also added a download button for downloading the relevant attachment. When clicking the download button, the app should split the last '.' to identify the file type and download the relevant file path. However, unfortunately, when clicking the download button, an error occurs.

error
Flutter错误:“PathNotFoundException: 无法打开文件,路径”

UI screenshot

Flutter错误:“PathNotFoundException: 无法打开文件,路径”

An example for the file Firestore URL

My code

IconButton(
  icon: Icon(Icons.download),
  onPressed: () async {
    // Get the file from _selectedFiles
    final file = _selectedFiles[index];

    // Open the download dialog
    final directory = await getExternalStorageDirectory();
    final savePath = path.join(directory!.path, 'Download', file.path.split('/').last);
    await showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text('Download'),
        content: Text('Do you want to download ${file.path.split('/').last}'),
        actions: [
          TextButton(
            child: Text('Cancel'),
            onPressed: () => Navigator.pop(context),
          ),
          TextButton(
            child: Text('Download'),
            onPressed: () async {
              // Download the file
              await http.get(Uri.parse(file.path)).then((response) async {
                final bytes = response.bodyBytes;
                await File(savePath).writeAsBytes(bytes);
              });

              // Close the dialog
              Navigator.pop(context);

              // Show a message to indicate that the download is complete
              ScaffoldMessenger.of(context).showSnackBar(
                SnackBar(content: Text('Download complete')),
              );
            },
          ),
        ],
      ),
    );
  },

),

path provider package

path_provider: ^2.0.2

How to solve this error?

AndroidManifest.xml
Flutter错误:“PathNotFoundException: 无法打开文件,路径”

Print savepath screenshot
Flutter错误:“PathNotFoundException: 无法打开文件,路径”

英文:

I built an app to upload attachments to Firebase Storage, with the URL saved in Firestore. The upload part works nicely. I also added a download button for downloading the relevant attachment. When clicking the download button, the app should split the last '.' to identify the file type and download the relevant file path. However, unfortunately, when clicking the download button, an error occurs.

error
Flutter错误:“PathNotFoundException: 无法打开文件,路径”

UI screenshot

Flutter错误:“PathNotFoundException: 无法打开文件,路径”

A example for the file firestore url

https://firebasestorage.googleapis.com/v0/b/petpulz-93d6f.appspot.com/o/records%2F49785b2d-5bc2-47c1-9ac2-2654627851de3518522212366212285.jpg?alt=media&token=4690a174-c094-4019-a540-17ca8437a69e.jpg

My code

IconButton(
  icon: Icon(Icons.download),
  onPressed: () async {
    // Get the file from _selectedFiles
    final file = _selectedFiles[index];

    // Open the download dialog
    final directory = await getExternalStorageDirectory();
    final savePath = path.join(directory!.path, 'Download', file.path.split('/').last);
    await showDialog(
      context: context,
      builder: (context) => AlertDialog(
        title: Text('Download'),
        content: Text('Do you want to download ${file.path.split('/').last}'),
        actions: [
          TextButton(
            child: Text('Cancel'),
            onPressed: () => Navigator.pop(context),
          ),
          TextButton(
            child: Text('Download'),
            onPressed: () async {
              // Download the file
              await http.get(Uri.parse(file.path)).then((response) async {
                final bytes = response.bodyBytes;
                await File(savePath).writeAsBytes(bytes);
              });

              // Close the dialog
              Navigator.pop(context);

              // Show a message to indicate that the download is complete
              ScaffoldMessenger.of(context).showSnackBar(
                SnackBar(content: Text('Download complete')),
              );
            },
          ),
        ],
      ),
    );
  },

),

path provider package

  path_provider: ^2.0.2

how to solve this error ?

** AndroidManifest.xml**
Flutter错误:“PathNotFoundException: 无法打开文件,路径”

print savepath screenshot
Flutter错误:“PathNotFoundException: 无法打开文件,路径”

答案1

得分: 2

"// change Directory and save path like this

final directory = await Directory('/storage/emulated/0/Download');

final savePath = path.join(directory!.path, file.path.split('/').last);

change directory because an above android 10 version devices not access to use /storage/emulated/0/Android/data directory"

英文:
// change Directory and save path like this

final directory = await  Directory('/storage/emulated/0/Download');

final savePath = path.join(directory!.path,file.path.split('/').last);

change directory because an above android 10 version devices not access to use /storage/emulated/0/Android/data directory

答案2

得分: 1

I solved the error and now file download working for android and ios prefectly.

  IconButton(
    icon: Icon(Icons.download),
    onPressed: () async {
      // Get the file from _selectedFiles
      final file = oneRecord!.fileUrls[index];

      // Generate a random file name
      final suffix = file.path.split('.').last.split('?').first;
      final randomName = '${randomString(10)}.$suffix';

      // Set the save path based on the platform
      String savePath;
      if (Platform.isIOS) {
        final directory = await getApplicationDocumentsDirectory();
        savePath = '${directory.path}/$randomName';
      } else if (Platform.isAndroid) {
        savePath = '/storage/emulated/0/Download/$randomName';
      } else {
        // Handle other platforms if necessary
        return;
      }

      // Open the download dialog
      await showDialog(
        context: context,
        builder: (context) =>
            AlertDialog(
          title: Text('Download'),
          content: Text(
              'Do you want to download $randomName ?'),
          actions: [
            TextButton(
              child: Text('Cancel'),
              onPressed: () =>
                  Navigator.pop(
                      context),
            ),
            TextButton(
              child:
                  Text('Download'),
              onPressed: () async {
                if (await Permission
                    .storage
                    .request()
                    .isGranted) {
                  await http
                      .get(Uri.parse(
                      file
                          .path))
                      .then(
                          (response) async {
                        final bytes =
                            response
                                .bodyBytes;
                        await File(
                            savePath)
                            .writeAsBytes(
                            bytes);
                      });
                }

                // Close the dialog
                Navigator.pop(
                    context);

                // Show a message to indicate that the download is complete
                ScaffoldMessenger
                    .of(context)
                    .showSnackBar(
                  SnackBar(
                      content: Text(
                          'Download complete')),
                );
              },
            ),
          ],
        ),
      );
    },
  ),

For the iOS path, you should import:

import 'package:path_provider/path_provider.dart';

To use this import, you need to install the relevant package:

path_provider: ^2.0.2

Additionally, make sure to set permissions in the AndroidManifest.xml file for Android and in the info.plist file for iOS.

info.plist (iOS):
Add these code lines:

<key>LSSupportsOpeningDocumentsInPlace</key>
<true/>
<key>UIFileSharingEnabled</key>
<true/>

These permissions are for working with documents.

AndroidManifest.xml (Android):
Add these permission code lines:

<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.ACCESS_WIFI_STATE" />
<uses-permission android:name="android.permission.ACCESS_NETWORK_STATE" />
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>

With this code, any file type can be downloaded to the device, not just PDF files and images. On Android, the downloaded files will be saved to the download folder, and on iOS, they will be saved to the Files app in a separate folder created using the application name.

英文:

I solved the error and now file download working for android and ios prefectly.

  IconButton(
icon: Icon(Icons.download),
onPressed: () async {
// Get the file from _selectedFiles
final file = oneRecord!.fileUrls[index];
// Generate a random file name
final suffix = file.path.split(&#39;.&#39;).last.split(&#39;?&#39;).first;
final randomName = &#39;${randomString(10)}.$suffix&#39;;
// Set the save path based on the platform
String savePath;
if (Platform.isIOS) {
final directory = await getApplicationDocumentsDirectory();
savePath = &#39;${directory.path}/$randomName&#39;;
} else if (Platform.isAndroid) {
savePath = &#39;/storage/emulated/0/Download/$randomName&#39;;
} else {
// Handle other platforms if necessary
return;
}
// Open the download dialog
await showDialog(
context: context,
builder: (context) =&gt;
AlertDialog(
title: Text(&#39;Download&#39;),
content: Text(
&#39;Do you want to download $randomName ?&#39;),
actions: [
TextButton(
child: Text(&#39;Cancel&#39;),
onPressed: () =&gt;
Navigator.pop(
context),
),
TextButton(
child:
Text(&#39;Download&#39;),
onPressed: () async {
if (await Permission
.storage
.request()
.isGranted) {
await http
.get(Uri.parse(
file
.path))
.then(
(response) async {
final bytes =
response
.bodyBytes;
await File(
savePath)
.writeAsBytes(
bytes);
});
}
// Close the dialog
Navigator.pop(
context);
// Show a message to indicate that the download is complete
ScaffoldMessenger
.of(context)
.showSnackBar(
SnackBar(
content: Text(
&#39;Download complete&#39;)),
);
},
),
],
),
);
},
),

and for the ios path you should import

import &#39;package:path_provider/path_provider.dart&#39;;

for that import you need to install relevant package

path_provider: ^2.0.2

and also specially you need to give permisions in the AndroidManifest.xml file in android and info.plist file in ios folder

info.plist(ios)
add these code line

 &lt;key&gt;LSSupportsOpeningDocumentsInPlace&lt;/key&gt;
&lt;true/&gt;
&lt;key&gt;UIFileSharingEnabled&lt;/key&gt;
&lt;true/&gt;

simply these permissions are for the documents .

AndroidManifest.xml(android)
add these permission code lines

  &lt;uses-permission android:name=&quot;android.permission.INTERNET&quot; /&gt;
&lt;uses-permission android:name=&quot;android.permission.ACCESS_WIFI_STATE&quot; /&gt;
&lt;uses-permission android:name=&quot;android.permission.ACCESS_NETWORK_STATE&quot; /&gt;
&lt;uses-permission android:name=&quot;android.permission.READ_EXTERNAL_STORAGE&quot; /&gt;
&lt;uses-permission android:name=&quot;android.permission.WRITE_EXTERNAL_STORAGE&quot;/&gt;
&lt;uses-permission android:name=&quot;android.permission.WRITE_EXTERNAL_STORAGE&quot;/&gt;

On Android, the downloaded files should be saved to the download folder, and on iOS, they should be saved to the Files app in a separate folder created using the application name.

I should clarify that with this code, any file type can be downloaded to the device, not just PDF files and images.

huangapple
  • 本文由 发表于 2023年5月6日 17:52:10
  • 转载请务必保留本文链接:https://go.coder-hub.com/76188234.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定