'PDF file download from url and store on internal storage then try to open it from any PDF reader its shows file format is not supported in flutter

I am trying to open my downloaded PDF file within my app then it shows fine, but when I open it from any other app like PDF reader its shows file format is not supported.

  • PDF file is stored in this directory:
    internal storage/MyApp/pdf
  • I want to access that PDF file from any PDF reader or its open from my file manager so what needs to do.
  • I am not using path directory of getExternalStorageDirectory()
  • I give internal storage path direct like /storage/emulated/0/MyApp

This is my complete code

import 'dart:io';
import 'package:flutter/material.dart';
import 'package:logger/logger.dart';
import 'package:open_file/open_file.dart';
import 'package:path_provider/path_provider.dart';
import 'package:http/http.dart' as http;

void main(){
  runApp(new MaterialApp(
      debugShowCheckedModeBanner: false,
      home: new FileDownloadView()

  ));
}


class FileDownloadView extends StatefulWidget {
  @override
  _FileDownloadViewState createState() => _FileDownloadViewState();
}

class _FileDownloadViewState extends State<FileDownloadView> {
  String _filePath = "";

  Future<String> get _localDevicePath async {

    final _devicePath = await getExternalStorageDirectory();
    return _devicePath.path;
  }

  Future<File> _localFile({String path, String type}) async {
    String _path = await _localDevicePath;

    var _newPath = await Directory("/storage/emulated/0/$path").create();
    return File("${_newPath.path}/pdf.$type");
  }

  Future _downloadSamplePDF() async {
    final _response =
    await http.get("https://firebasestorage.googleapis.com/v0/b/text-recognition-28371.appspot.com/o/Direct%20Recruitment%202020.pdf?alt=media&token=114498c1-0e84-48e0-bda0-15d4b688f745");
    if (_response.statusCode == 200) {
      final _file = await _localFile(path: "MyApp", type: "pdf");
      final _saveFile = await _file.writeAsBytes(_response.bodyBytes);

      Logger().i("File write complete. File Path ${_saveFile.path}");
      setState(() {
        _filePath = _saveFile.path;
      });
    } else {
      Logger().e(_response.statusCode);
    }
  }

  Future _downloadSampleVideo() async {
    final _response = await http.get(
        "https://sample-videos.com/video123/mp4/720/big_buck_bunny_720p_2mb.mp4");
    if (_response.statusCode == 200) {
      final _file = await _localFile(type: "mp4", path: "videos");
      final _saveFile = await _file.writeAsBytes(_response.bodyBytes);
      Logger().i("File write complete. File Path ${_saveFile.path}");
      setState(() {
        _filePath = _saveFile.path;
      });
    } else {
      Logger().e(_response.statusCode);
    }
  }


  @override
  Widget build(BuildContext context) {
    return Scaffold(
      body: Center(
        child: Column(
          mainAxisAlignment: MainAxisAlignment.center,
          children: <Widget>[
            FlatButton.icon(
              icon: Icon(Icons.file_download),
              label: Text("Sample Pdf"),
              onPressed: () {
                _downloadSamplePDF();



              },
            ),
            FlatButton.icon(
              icon: Icon(Icons.file_download),
              label: Text("Sample Videos"),
              onPressed: () {
                _downloadSampleVideo();

              },
            ),
            Text(_filePath),
            FlatButton.icon(
              icon: Icon(Icons.shop_two),
              label: Text("Show"),
              onPressed: () async {
                final _openFile = await OpenFile.open(_filePath);
                Logger().i(_openFile);
              },
            ),
          ],
        ),
      ),
    );
  }
}

Android Manifest

<manifest xmlns:android="http://schemas.android.com/apk/res/android"
    package="com.example2.downloder_app">
    <uses-permission android:name="android.permission.INTERNET"></uses-permission>
    <uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"></uses-permission>
    <uses-permission android:name="android.permission.ACCESS_NETWORK_STATE"></uses-permission>
    <uses-permission android:name="android.permission.READ_PHONE_STATE"></uses-permission>
    <uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE" />
    <!-- io.flutter.app.FlutterApplication is an android.app.Application that
         calls FlutterMain.startInitialization(this); in its onCreate method.
         In most cases, you can leave this as-is, but you if you want to provide
         additional functionality it is fine to subclass or reimplement
         FlutterApplication and put your custom class here. -->
    <application
        android:name="io.flutter.app.FlutterApplication"
        android:label="downloder_app"
        android:icon="@mipmap/ic_launcher"
        android:testOnly="false">
        <activity
            android:name=".MainActivity"
            android:launchMode="singleTop"
            android:theme="@style/LaunchTheme"
            android:configChanges="orientation|keyboardHidden|keyboard|screenSize|smallestScreenSize|locale|layoutDirection|fontScale|screenLayout|density|uiMode"
            android:hardwareAccelerated="true"
            android:windowSoftInputMode="adjustResize">
            <intent-filter>
                <action android:name="android.intent.action.MAIN"/>
                <category android:name="android.intent.category.LAUNCHER"/>
            </intent-filter>
        </activity>
        <!-- Don't delete the meta-data below.
             This is used by the Flutter tool to generate GeneratedPluginRegistrant.java -->
        <meta-data
            android:name="flutterEmbedding"
            android:value="2" />
    </application>
</manifest>


Solution 1:[1]

It's possible that you need to add permission_handler on your workflow to enable write permission on the device's storage.

Were you able to verify if the file downloaded was indeed written in storage? If the file has been downloaded but has 0 bytes, then it's likely that there has been an issue.

I suggest avoiding hard coded root path as it may change depending on the platform-version that you're using. Instead, you may consider using getApplicationDocumentsDirectory() - this should write the file inside the app directory. If the data needs to be visible to the user, you can use getExternalStorageDirectory() for Android.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Omatt