从url下载pdf,在flutter中保存到android中的手机本地存储

Posted

技术标签:

【中文标题】从url下载pdf,在flutter中保存到android中的手机本地存储【英文标题】:Download pdf from url, save to phones local storage in android in flutter 【发布时间】:2020-08-13 11:50:42 【问题描述】:

我正在做一个项目,一旦点击按钮,我需要从 URL 下载 pdf 文件,并将其存储到手机存储中(可能是下载文件夹)。

关于如何做到这一点的任何想法?正在下载的文件也不总是相同的,可以是从 pdf 到图像的任何文件。

【问题讨论】:

提前致谢!! 你可以使用像cropper这样的图像裁剪器 【参考方案1】:

您可以使用Dio 包将文件下载到本地存储,使用Dio().download

response = await dio.download("https://www.google.com/", "./xx.html");

您也可以查看open source project 作为参考

【讨论】:

是否有可能“Dio”链接无意中指向了与开源项目相同的站点?如果是这样的话,可以在pub.dev/packages/dio 找到 Dio 哦,是的!纠正了这一点。谢谢指出 我使用了 dio.download 并检查了它是否保存在设备中。它正确保存,但我没有收到任何消息,它不在下载中,然后仅在目录中归档。您是如何将通知视为已保存文件的?你是手动做的吗?【参考方案2】:

以下代码适用于 iosandroid。如果您要下载图片,请将“.pdf”替换为“.jpg”。

pubspec.yaml中,将以下代码粘贴到依赖项下

dio: any
path_provider: any
file_utils: any
permission_handler: any

android/app/src/main/AndroidManifest.xml 中,将下面的行粘贴到<application> 标记之外

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

下面是代码:

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:dio/dio.dart';
import 'package:path_provider/path_provider.dart';
import 'dart:async';
import 'package:file_utils/file_utils.dart';
import 'package:permission_handler/permission_handler.dart';
import 'package:intl/intl.dart';

void main() => runApp(Downloader());

class Downloader extends StatelessWidget 
  @override
  Widget build(BuildContext context) => MaterialApp(
    title: "File Downloader",
    debugShowCheckedModeBanner: false,
    home: FileDownloader(),
    theme: ThemeData(primarySwatch: Colors.blue),
  );


class FileDownloader extends StatefulWidget 
  @override
  _FileDownloaderState createState() => _FileDownloaderState();


class _FileDownloaderState extends State<FileDownloader> 

final pdfUrl = "https://www.w3.org/WAI/ER/tests/xhtml/testfiles/resources/pdf/dummy.pdf";
  
  bool downloading = false;
  var progress = "";
  var path = "No Data";
  var platformVersion = "Unknown";
  var _onPressed;
  Directory externalDir;

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

String convertCurrentDateTimeToString() 
    String formattedDateTime =
    DateFormat('yyyyMMdd_kkmmss').format(DateTime.now()).toString();
    return formattedDateTime;
  

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

    final status = await Permission.storage.request();
    if (status.isGranted) 
      String dirloc = "";
      if (Platform.isAndroid) 
        dirloc = "/sdcard/download/";
       else 
        dirloc = (await getApplicationDocumentsDirectory()).path;
      

      try 
        FileUtils.mkdir([dirloc]);
        await dio.download(pdfUrl, dirloc + convertCurrentDateTimeToString() + ".pdf",
            onReceiveProgress: (receivedBytes, totalBytes) 
          print('here 1');
              setState(() 
                downloading = true;
                progress = ((receivedBytes / totalBytes) * 100).toStringAsFixed(0) + "%";
                print(progress);
              );
              print('here 2');
            );
       catch (e) 
        print('catch catch catch');
        print(e);
      

      setState(() 
        downloading = false;
        progress = "Download Completed.";
        path = dirloc + convertCurrentDateTimeToString() + ".pdf";
      );
      print(path);
      print('here give alert-->completed');
     else 
      setState(() 
        progress = "Permission Denied!";
        _onPressed = () 
          downloadFile();
        ;
      );
    
  

  @override
  Widget build(BuildContext context) => Scaffold(
      appBar: AppBar(
        title: Text('File Downloader'),
      ),
      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: 10.0,
                  ),
                  Text(
                    'Downloading File: $progress',
                    style: TextStyle(color: Colors.white),
                  ),
                ],
              ),
            ),
          )
              : Column(
            mainAxisAlignment: MainAxisAlignment.center,
            children: <Widget>[
              Text(path),
              MaterialButton(
                child: Text('Request Permission Again.'),
                onPressed: _onPressed,
                disabledColor: Colors.blueGrey,
                color: Colors.pink,
                textColor: Colors.white,
                height: 40.0,
                minWidth: 100.0,
              ),
            ],
          )));

【讨论】:

【参考方案3】:

我希望这会对你有所帮助。检查文件是否已经存在,如果没有,则使用 URL 获取文件并将其保存在应用程序目录中。

Future<File> createFile() async 
    try 
      /// setting filename 
      final filename = widget.docPath;

      /// getting application doc directory's path in dir variable
      String dir = (await getApplicationDocumentsDirectory()).path;

      /// if `filename` File exists in local system then return that file.
      /// This is the fastest among all.
      if (await File('$dir/$filename').exists()) return File('$dir/$filename');

      ///if file not present in local system then fetch it from server

      String url = widget.documentUrl;

      /// requesting http to get url
      var request = await HttpClient().getUrl(Uri.parse(url));

      /// closing request and getting response
      var response = await request.close();

      /// getting response data in bytes
      var bytes = await consolidateHttpClientResponseBytes(response);

      /// generating a local system file with name as 'filename' and path as '$dir/$filename'
      File file = new File('$dir/$filename');

      /// writing bytes data of response in the file.
      await file.writeAsBytes(bytes);

      /// returning file.
      return file;
    

    /// on catching Exception return null
    catch (err) 
      errorMessage = "Error";
      print(errorMessage);
      print(err);
      return null;
    
  

【讨论】:

我希望在下载完成时使用确定按钮弹出一个弹出窗口,然后单击确定打开下载的文件 这个函数正在返回一个文件,你可以等待future完成,在你得到文件后只需使用AlertDialog显示弹出窗口。

以上是关于从url下载pdf,在flutter中保存到android中的手机本地存储的主要内容,如果未能解决你的问题,请参考以下文章

从 URL 下载 TXT 文件并保存到 Flutter Web 上的 PC

在 Flutter 循环进度指示器中显示下载百分比

Flutter Web:从 URL 下载文件而不打开它

如何让用户从 Flutter 应用程序下载/保存文件?

如何测量从 URL 下载的 PDF 的大小

从 webbrowser 控件保存 pdf 文档