如何在Flutter/Dart中将互联网上的文件下载并保存到Android设备的内部存储中?

5

我需要将eg.jpg文件保存到"internalstorage/appname/files/"目录中,并在文件夹中已存在文件时显示通知。当按下按钮或启动活动时,它应该使用Dart代码将文件下载到Android设备的本地存储中。请帮我找到解决方案。

**code:**
   import 'dart:io';
  import 'dart:async';
  import 'package:flutter/material.dart';
 import 'package:flutter_downloader/flutter_downloader.dart';
 import './landing_page.dart';
 import 'package:dio/dio.dart';
 import 'package:path_provider/path_provider.dart';
 import 'package:simple_permissions/simple_permissions.dart';
 import 'package:flutter/services.dart';


 class MoviesPage extends StatefulWidget {

  @override
 State createState() => new MoviesPageState();
 }

 class MoviesPageState extends State<MoviesPage> {
  final dUrl ="https://cdn.putlockers.es/download/0BBCA7584749D4E741747E32E6EB588AEA03E40F";
 bool downloading = false;
 var progressString = "";
static const MethodChannel _channel =
     const MethodChannel('flutter_downloader');

 @override
  void initState() {
    super.initState();
   downloadFile();

   }


  Future<void> downloadFile() async {
    Dio dio = Dio();

    try {
     var dir = await getApplicationDocumentsDirectory();

     await dio.download(dUrl, "${dir.path}/file.torrent",
          onProgress: (rec, total) {
          print("Rec: $rec , Total: $total");

       setState(() {
        downloading = true;
        progressString = ((rec / total) * 100).toStringAsFixed(0) + "%";
      });
     });
      } catch (e) {
      print(e);
      }

    setState(() {
     downloading = false;
     progressString = "Completed";
     });
     print("Download completed");
     }
    @override
     Widget build(BuildContext context) {
     return Scaffold(
          appBar: AppBar(
         title: Text("AppBar"),
        ),
     body: Center(
       child: downloading
           ? Container(
               height: 120.0,
              width: 200.0,
               child: Card(
                 color: Colors.black,
                 child: Column(
                     mainAxisAlignment: MainAxisAlignment.center,
                     children: <Widget>[
                       CircularProgressIndicator(),
                      SizedBox(
                    height: 20.0,
                  ),
                  Text(
                    "Downloading File: $progressString",
                    style: TextStyle(
                      color: Colors.white,
                    ),
                  )
                ],
              ),
            ),
          )
        : Text("No Data"),
  ),
);
 }
}

感谢您提前的帮助。请以完整和详尽的方式发布您的解决方案。

如果您在问题中发布的代码有错误,请说明实际出现了什么问题。它是否给出了任何错误信息? - Arto Bendiken
正在下载文件,但未存储到本地存储。需要将文件存储到手机中的myfolder文件夹中。 - PrakashKing
我需要在我的应用程序中有一个永久存储的文件。 - PrakashKing
static var httpClient = new HttpClient(); Future<File> _downloadFile() async { String url = "https://cdn.putlockers.es/download/0BBCA7584749D4E741747E32E6EB588AEA03E40F"; String filename="复仇者联盟.torrent"; http.Client client = new http.Client(); var req = await client.get(Uri.parse(url)); var bytes = req.bodyBytes; String dir = (await getApplicationDocumentsDirectory()).path; File file = new File('$dir/$filename'); await file.writeAsBytes(bytes); return file; } - PrakashKing
谢谢,我解决了。请给我的问题和个人资料投票 :) - PrakashKing
1个回答

4
我已检查了你发布的最小复现代码,看起来你正在使用Flutter插件dio下载文件。我重新使用了你代码中的Future<void> downloadFile()方法,并稍作修改以检查插件是否按预期工作。截至dio插件3.0.10版本,dio.download()上的onProgress现在是onReceiveProgress,但它仍然具有相同的功能。
以下是基于你的代码稍作修改后用于下载图像文件的方法。
Future downloadFile() async {
  Dio dio = Dio();
  var dir = await getApplicationDocumentsDirectory();
  var imageDownloadPath = '${dir.path}/image.jpg';
  await dio.download(imageSrc, imageDownloadPath,
      onReceiveProgress: (received, total) {
    var progress = (received / total) * 100;
    debugPrint('Rec: $received , Total: $total, $progress%');
    setState(() {
      downloadProgress = received.toDouble() / total.toDouble();
    });
  });
  // downloadFile function returns path where image has been downloaded
  return imageDownloadPath;
}

插件正常工作,成功下载图像文件。但是我无法验证您如何确定您正在尝试下载的图像在您的重现中失败。在我的示例应用程序中,Future downloadFile() 返回一个字符串,其中存储了图像路径。然后,我使用此来更新Image Widget以显示已下载的图像-这确定下载已成功完成。
以下是完整的示例应用程序。
import 'dart:io';

import 'package:dio/dio.dart';
import 'package:flutter/material.dart';
import 'package:path_provider/path_provider.dart';

void main() {
  runApp(MyApp());
}

class MyApp extends StatelessWidget {
  @override
  Widget build(BuildContext context) {
    return MaterialApp(
      title: 'Flutter Demo',
      theme: ThemeData(
        primarySwatch: Colors.blue,
        visualDensity: VisualDensity.adaptivePlatformDensity,
      ),
      home: MyHomePage(title: 'Flutter Demo Home Page'),
    );
  }
}

class MyHomePage extends StatefulWidget {
  MyHomePage({Key key, this.title}) : super(key: key);

  final String title;

  @override
  _MyHomePageState createState() => _MyHomePageState();
}

class _MyHomePageState extends State<MyHomePage> {
  final imageSrc = 'https://picsum.photos/250?image=9';
  var downloadPath = '';
  var downloadProgress = 0.0;
  @override
  Widget build(BuildContext context) {
    return Scaffold(
      appBar: AppBar(
        title: Text(widget.title),
      ),
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            Expanded(flex: 5, child: Image.network(imageSrc)),
            Expanded(
              flex: 2,
              child: Row(
                children: [
                  ElevatedButton(
                    // Download displayed image from imageSrc
                    onPressed: () {
                      downloadFile().catchError((onError) {
                        debugPrint('Error downloading: $onError');
                      }).then((imagePath) {
                        debugPrint('Download successful, path: $imagePath');
                        displayDownloadImage(imagePath);
                      });
                    },
                    child: Text('Download'),
                  ),
                  ElevatedButton(
                    // Delete downloaded image
                    onPressed: () {
                      deleteFile().catchError((onError) {
                        debugPrint('Error deleting: $onError');
                      }).then((value) {
                        debugPrint('Delete successful');
                      });
                    },
                    child: Text('Clear'),
                  )
                ],
              ),
            ),
            LinearProgressIndicator(
              value: downloadProgress,
            ),
            Expanded(
                flex: 5,
                child: downloadPath == ''
                // Display a different image while downloadPath is empty
                // downloadPath will contain an image file path on successful image download
                    ? Icon(Icons.image)
                    : Image.file(File(downloadPath))),
          ],
        ),
      ),
    );
  }

  displayDownloadImage(String path) {
    setState(() {
      downloadPath = path;
    });
  }

  Future deleteFile() async {
    final dir = await getApplicationDocumentsDirectory();
    var file = File('${dir.path}/image.jpg');
    await file.delete();
    setState(() {
      // Clear downloadPath on file deletion
      downloadPath = '';
    });
  }

  Future downloadFile() async {
    Dio dio = Dio();
    var dir = await getApplicationDocumentsDirectory();
    var imageDownloadPath = '${dir.path}/image.jpg';
    await dio.download(imageSrc, imageDownloadPath,
        onReceiveProgress: (received, total) {
      var progress = (received / total) * 100;
      debugPrint('Rec: $received , Total: $total, $progress%');
      setState(() {
        downloadProgress = received.toDouble() / total.toDouble();
      });
    });
    // downloadFile function returns path where image has been downloaded
    return imageDownloadPath;
  }
}

在示例应用程序中,单击“下载”按钮将下载位于屏幕顶部的网络图像。下载成功后,使用Image.file()在屏幕下部显示已下载的图像。

enter image description here


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