My goal is to download a file from an API server (pdf file in this case) and then I want to load that pdf and show it on the UI. I am using flutter_pdfview
and I am following this tutorial how to implement it . Firstly, permissions: In my android/app/build.gradle
targetSdkVersion
is 29 as well as compileSdkVersion
. In android/app/main/AndroidManifest.xml
i wrote bellow <application ... android:requestLegacyExternalStorage="true">
and I have added in the same folder these permissions.
<uses-permission android:name="android.permission.INTERNET"/>
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.READ_EXTERNAL_STORAGE"/>
Fetch request:
Future<File> getFile(String id) async {
_isLoading = true;
notifyListeners();
var headers = {
'Authorization': 'JWT ${_authenticatedUser.token}',
'Content-Type': 'application/x-www-form-urlencoded',
'Accept': 'application/json',
};
try {
final http.Response response = await http.get(
'api-host/pdf',
headers: headers);
var bytes = response.bodyBytes;
var dir = await getExternalStorageDirectory();// Option 1
//var dir = awiat getApplicationDocumentsDirectory(); //Option 2
File file = File("${dir.path}/mypdfonline.pdf");
File urlFile = await file.writeAsBytes(bytes);
if (response.statusCode != 200) {
_isLoading = false;
notifyListeners();
throw Exception('get error: statusCode= ${response.headers}');
}
_isLoading = false;
notifyListeners();
return urlFile;
} catch (e) {
_isLoading = false;
notifyListeners();
throw Exception("Error opening url file");
}
}
With option 1, I have found pdf file inside my internal storage, but it still gives me an error. With Option 2 like the guy did it, i couldn't find it anywhere on my device. Also, I have granted storage access manually in my phone but that also didn't help.
class ImagePreview extends StatefulWidget {
final MainModel model;
final String id;
ImagePreview(this.model, this.id);
@override
State<StatefulWidget> createState() {
return _ImagePreviewState();
}
}
class _ImagePreviewState extends State<ImagePreview> {
String urlPDFPath = "";
int _totalPages = 0;
int _currentPage = 0;
bool pdfReady = false;
PDFViewController _pdfViewController;
@override
void initState() {
super.initState();
widget.model.getFile(widget.id).then((value) {
setState(() {
urlPDFPath = value.path;
print(urlPDFPath);
});
});
}
@override
Widget build(BuildContext context) {
return Scaffold(
appBar: AppBar(
title: Text('PDF Preview'),
),
body: Stack(
children: <Widget>[
PDFView(
filePath: urlPDFPath,
autoSpacing: true,
enableSwipe: true,
pageSnap: true,
swipeHorizontal: true,
nightMode: false,
onError: (e) {
print(e);
},
onRender: (_pages) {
setState(() {
_totalPages = _pages;
pdfReady = true;
});
},
onViewCreated: (PDFViewController vc) {
_pdfViewController = vc;
},
onPageChanged: (int page, int total) {
setState(() {});
},
onPageError: (page, e) {},
),
!pdfReady
? Center(
child: CircularProgressIndicator(),
)
: Offstage(),
],
),
floatingActionButton: Row(
mainAxisAlignment: MainAxisAlignment.end,
children: <Widget>[
_currentPage > 0
? FloatingActionButton.extended(
backgroundColor: Colors.red,
label: Text("Go to ${_currentPage - 1}"),
onPressed: () {
_currentPage -= 1;
_pdfViewController.setPage(_currentPage);
},
)
: Offstage(),
_currentPage + 1 < _totalPages
? FloatingActionButton.extended(
backgroundColor: Colors.green,
label: Text("Go to ${_currentPage + 1}"),
onPressed: () {
_currentPage += 1;
_pdfViewController.setPage(_currentPage);
},
)
: Offstage(),
],
),
);
}
}