从网址下载文件,保存到手机存储

40

我正在开发一个项目,需要在点击按钮后从URL下载文件,并将其存储到手机存储空间(可能是下载文件夹)。

有什么好的建议吗?被下载的文件类型也不总是相同的,可以是图片或PDF等任何文件。


5
请提供代码以展示您试图达成的目标,以及您尝试过什么和失败的地方。StackOverflow不是一个码农服务网站。参考链接:https://flutter.cn/docs/cookbook/networking/fetch-data,https://flutter.cn/docs/cookbook/persistence/reading-writing-files - Günter Zöchbauer
1
在iOS和Android中,你将下载的文件存储在哪个位置? - Millie Hudson
5个回答

28
使用https://pub.dartlang.org/packages/flutter_downloader。别忘了进行平台配置。
基本上,这就是你应该使用该包的方式。链接中有一个详细的长示例。
final taskId = await FlutterDownloader.enqueue(
  url: 'your download link',
  savedDir: 'the path of directory where you want to save downloaded files',
  showNotification: true, // show download progress in status bar (for Android)
  openFileFromNotification: true, // click on notification to open downloaded file (for Android)
);

编辑:有些人说顶部的包没有得到很好的维护。试试这个吧 https://pub.dev/packages/flowder

1
非常感谢。简直不敢相信我之前没找到这个库。顺便问一下,如何指定下载文件夹的路径?我知道在 Linux 等系统中如何在其中移动,但在这里该怎么做呢? - petek
1
我离成功很近了,但是我无法获取工作权限。我的应用程序已经有了存储权限,甚至为此安装了权限插件,但我仍然收到"操作系统错误:权限被拒绝,errno = 13"的提示..有什么想法吗?尝试找到解决方案,但似乎不起作用。 - petek
1
你是否针对特定平台进行了权限设置?例如在Android中的清单文件(Manifest)? - westdabestdb
4
这个包裹有很多问题! - xSuperMu
1
这个软件包存在问题并且没有得到维护。@westdabestdb,是否还有其他选项? - Dani
显示剩余4条评论

16
如果您想从URL下载和保存文件,而不使用外部库,您可以使用此代码。它对我有效,但我没有在大文件上进行测试。祝你好运。
Future<String> downloadFile(String url, String fileName, String dir) async {
        HttpClient httpClient = new HttpClient();
        File file;
        String filePath = '';
        String myUrl = '';
    
        try {
          myUrl = url+'/'+fileName;
          var request = await httpClient.getUrl(Uri.parse(myUrl));
          var response = await request.close();
          if(response.statusCode == 200) {
            var bytes = await consolidateHttpClientResponseBytes(response);
            filePath = '$dir/$fileName';
            file = File(filePath);
            await file.writeAsBytes(bytes);
          }
          else
            filePath = 'Error code: '+response.statusCode.toString();
        }
        catch(ex){
          filePath = 'Can not fetch url';
        }
    
        return filePath;
      }

对于 Android,请不要忘记在清单文件中添加以下行,否则在构建 APK 后将无法在实际设备上运行:

<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" />

@MillieHudson 将文件保存到设备上的路径对应用程序的性能没有影响。您处理下载的方式会影响性能。 - Pierre
它适用于Flutter Web吗? - Muhammad Umair Saqib
Muhammad Umair Saqib 我没有在网页上测试,因为我专注于移动开发。但你可以检查一下,我认为这不需要太多时间。 - Murat Kurbanov
如何指定目录,以便在iOS手机上也能正常工作? - Harsha

15
static var httpClient = new HttpClient();
Future<File> _downloadFile(String url, String filename) async {
  var request = await httpClient.getUrl(Uri.parse(url));
  var response = await request.close();
  var bytes = await consolidateHttpClientResponseBytes(response);
  String dir = (await getApplicationDocumentsDirectory()).path;
  File file = new File('$dir/$filename');
  await file.writeAsBytes(bytes);
  return file;
}

它下载到哪里了?我在安卓的“下载”文件夹中没有找到已下载的文件。有什么建议吗? - Kamlesh
3
没什么发生... - Nehal Jaisalmeria
在这个例子中,使用 https://pub.dev/packages/path_provider 中的 getApplicationDocumentsDirectory() 方法。因此,下载的文件位于 data/data/com.example.app(这里是您的应用程序包名称)/app_flutter/downloaded_file 下。您可以通过设备文件浏览器打开此路径。 - Murat Kurbanov

7

0
 Future<String?> _saveFileToDevice(String filename, List<int> data) async {
// Get the path to the app's documents directory
var status = await Permission.storage.status;
if (!status.isGranted) {
  await Permission.storage.request();
}

var dir = Platform.isAndroid
    ? '/storage/emulated/0/Download'
    : (await getApplicationDocumentsDirectory()).path;

// Create the file and write the data to it
var file = File('$dir/$filename');

bool alreadyDownloaded = await file.exists();

String incrementCount(String fileName) {
  int dotIndex = fileName.lastIndexOf('.');
  String newFileName = fileName.substring(0, dotIndex) +
      "(${count += 1})" +
      fileName.substring(dotIndex);

  return newFileName;
}

if (alreadyDownloaded) {
  String newFileName = incrementCount(file.path);

  var newFile = File('$newFileName');
  await newFile.writeAsBytes(data, flush: true);

  String subStringFileName = newFileName.substring(29);
  CommonWidgets.makeToast(
      fontSize: 14,
      toastMsg: '${subStringFileName} saved to Downloads Folder');

  file = newFile;
  print('modified updating ....--> $file');
} else {
  await file.writeAsBytes(data, flush: true);

  CommonWidgets.makeToast(
      fontSize: 14,
      toastMsg: '${filename} saved to Downloads Folder');
}

return 'file://${file.path}';
}

这个函数将下载Uint8List字节,我们需要将文件转换为Uint8List字节


网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接