Max33
Max33

Reputation: 71

how to show a pdf fetched from an API response in flutter?

I am working in a project where I have to show certificate that the user finished a course, there is an URL of the API that uses the get method within a token to have acces to a pdf file, the problem is that I do not know how to show or transform that response into a pdf, using flutter, I tried to use the url_launcher dependency because in the browser shows the pdf normally, but the problem is that it I need to pass a token to that url. the second thing that i tried was to fetched the response of the api and save it in a temporal file and use flutter_pdfview dependency but it shows errors. this is how the response of the api looks like:

%PDF-1.4
1 0 obj
<<
/Title (þÿ)
/Creator (þÿ)
/Producer (þÿQt 5.5.1)
/CreationDate (D:20211120205047)
>>
endobj
2 0 obj
<<
/Type /Catalog
/Pages 3 0 R
>>
endobj
4 0 obj
<<
/Type /ExtGState
/SA true
/SM 0.02
/ca 1.0
/CA 1.0
/AIS false

this is what I tried:

 Future LoadPDF(APIurl)async {
    Map<String,String> Headers={
      'Content-type': 'application/json; charset=UTF-8',
      'Accept': 'application/json',
      'Authorization': 'Bearer $userToken'
    };
    final response = await http.get(Uri.parse(APIurl),headers: Headers);
    final bytes = response.bodyBytes;
    // print(response.bodyBytes);
    var dir = await getTemporaryDirectory();
    File file = File(dir.path + "/data.pdf"); 
    await file.writeAsBytes(bytes, flush: true);
    setState(() {
    loadDocument(file);
    });
    // return file;
    
  }

Upvotes: 7

Views: 7633

Answers (3)

Siddharth Sogani
Siddharth Sogani

Reputation: 349

Here is how I solved it:

Future<http.Response> apiCall(String fileId, String clientId) async {
String token = (await _storage.read(key: 'token')).toString();
final url = Uri.parse('$BASE_URL/oauth/notes/upload/view/$fileId/$clientId');
final headers = {"Authorization" : "Bearer $token", "Accept" : "*/*", "Accept-Encoding" : "gzip, deflate, br", "Connection": "keep-alive"};
final response = await http.get(url, headers: headers);
return response;

}

Future<File?> getContent(String fileId, String clientId, String extension) async {
//this is the api mentioned in next part
http.Response res = await api.apiCall(fileId, clientId);
dynamic response = res.bodyBytes;

if (response != null) {
  final Directory? appDir = Platform.isAndroid
      ? await getExternalStorageDirectory()
      : await getApplicationDocumentsDirectory();
  String tempPath = appDir!.path;
  final String fileName =
      DateTime.now().microsecondsSinceEpoch.toString() + extension;
  File file = File('$tempPath/$fileName');
  if (!await file.exists()) {
    await file.create();
  }
  await file.writeAsBytes(response);
  return file;
}

}

File? file = await contentService.getContent(
              fileid,
              id,
              '.pdf');
          if (file != null) {
            final String? result = await openFile(file.path.toString());
            if (result != null) {
              print('result');
              print(result);
              // Warning
            }
          }

static Future<String?> openFile(String url) async {
final OpenResult result = await OpenFile.open(url);

}

Upvotes: 5

Suganya
Suganya

Reputation: 439

Hi I got the same response as you. Here I used Dio api structure. Take this as reference. Below code work fine for me.

Future<File?> downloadPDF(String applicantId, String templateId) async {
try {
  final response = await dioClient.post('xxxxxx/pdfService/pdfOperation/downloadPDF', data:DownloadRequestDTO(applicantId, templateId), headers: <String, dynamic>{
'Content-Type': 'application/json'}, options: Options(responseType: ResponseType.bytes));
  if (response != null) {
    final Directory? appDir = Platform.isAndroid
        ? await getExternalStorageDirectory()
        : await getApplicationDocumentsDirectory();
    String tempPath = appDir!.path;
    final String fileName =
        DateTime.now().microsecondsSinceEpoch.toString() + '-' + 'akt.pdf';
    File file = new File('$tempPath/$fileName');
    if (!await file.exists()) {
      await file.create();
    }
    await file.writeAsBytes(response);
    return file;
  }
  throw DownloadException('The download failed.', response);
} catch (value) {
  if (value is DioError) {
    print(value.response);
  }
  print(value.toString());
}

}

Then use open_file package to open downloaded file

static Future<String?> openFile(String url) async {
final OpenResult result = await OpenFile.open(url);
switch (result.type) {
  case ResultType.error:
    return result.message;
  case ResultType.fileNotFound:
    return LocaleKeys.fileNotFound.tr();
  case ResultType.noAppToOpen:
    return LocaleKeys.noAppToOpen.tr();
  case ResultType.permissionDenied:
    return LocaleKeys.permissionDenied.tr();
  default:
    return null;
}}

And call this functions as below

Future<void> downloadAndOpenFile(BuildContext context) async {
try {
  File? file = await downloadPDF('1234', 'xxxxxx');
  if (file != null) {
    final String? result = await openFile(file.path.toString());
    if (result != null) {
      // Warning
    }
  }
} catch (e) {
  print(e);
}}

Upvotes: 3

AbdKa
AbdKa

Reputation: 206

you can use flutter_pdfview package to show pdf:

loadDocument(file) {
    PDFView(
      filePath: file.path,
      enableSwipe: true,
      swipeHorizontal: true,
      autoSpacing: false,
      pageFling: false,
      onRender: (_pages) {
        setState(() {
          pages = _pages;
          isReady = true;
        });
      },
      onError: (error) {
        print(error.toString());
      },
      onPageError: (page, error) {
        print('$page: ${error.toString()}');
      },
      onViewCreated: (PDFViewController pdfViewController) {
        _controller.complete(pdfViewController);
      },
      onPageChanged: (int page, int total) {
        print('page change: $page/$total');
      },
    ),
}

Upvotes: 0

Related Questions