Download pdf from url, save to phones local storage in android in flutter

9,185

Solution 1

You can use the Dio package to download files to your local storage using Dio().download

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

Also you can check out this open source project as reference

Solution 2

I hope this would help you. Check if file is already present, if not then use the URL to fetch the file and save it in application directory.

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;
    }
  }

Solution 3

The below code works on both iOS and Android. Replace ".pdf" with ".jpg" if you are looking for downloading an image.

In pubspec.yaml, paste the below code under dependencies

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

In android/app/src/main/AndroidManifest.xml paste the below lines outside the <application> tags

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

Below is the code :

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,
              ),
            ],
          )));
}
Share:
9,185
vivek
Author by

vivek

Updated on December 20, 2022

Comments

  • vivek
    vivek over 1 year

    I'm working on a project, that requires me to download a pdf file from URL, once a button is tapped, and store it to phone storage (probably downloads folder).

    Any ideas on how to do this? The file that is being downloaded is also not always the same and can be anything from an pdf to image.

    • vivek
      vivek about 4 years
      Thanks in advance !!
    • GGK stands for Ukraine
      GGK stands for Ukraine about 4 years
      You can use an image cropper like cropper
  • vivek
    vivek about 4 years
    i want a popup when download completed with ok button and on click ok open the downloaded file
  • Jagraj Singh
    Jagraj Singh about 4 years
    This function is returning a file, you can wait for future to complete and after you got the file simply use AlertDialog to show pop up.
  • Liberatys
    Liberatys almost 4 years
    Is it possible that the "Dio" link unintentionally leads to the same site as the open-source project? If it were the case, Dio could be found at pub.dev/packages/dio
  • JideGuru
    JideGuru almost 4 years
    Ohh yea! corrected that. Thanks for pointing it out
  • AyadRocketfy
    AyadRocketfy over 3 years
    I have used the dio.download and I checked if it saved in the device. It saves correctly but I don't receive any message and its not in downloads then file just in a directory. How did yo make to see the notification as a saved file? Did you make that manualy?