[Flutter] 암호화된 PDF 파일 열어서 뷰어로 보여주기

Elen li·2021년 11월 27일
0

해당 포스트에서는 아래와 같은 라이브러리가 필요합니다.

  • PDF 해독: syncfusion_flutter_pdf: ^19.1.55-beta
  • PDF 뷰어: native_pdf_view: ^4.1.0
  • 참고사항 1)
    PDF 해독 메소드와 PDF 뷰어에 있는 클래스 중에 'PdfDocument()'가 겹칩니다.
    두개가 컴파일 과정에서 헷갈리지 않도록 import 부분에 as로서 별칭을 달아줍니다.
    그리고 저희가 사용할 PdfDocument()는 syncfusion의 클래스입니다.
import 'package:native_pdf_view/native_pdf_view.dart';
import 'package:syncfusion_flutter_pdf/pdf.dart' as syncPdf;
  • 참고사항 2)
    syncfusion에서 만든 PDF 뷰어에 적용해도 가능합니다.
    제가 native_pdf_view 적용했던 이유는 단순히 기존에 사용해서 구현되었던 기능의 수정을 최소화 하기 위함이었습니다.
    native_pdf_view의 PdfDocument()는 비밀번호를 받아서 파일을 읽는 기능이 없습니다.

1. 비밀번호 해독하기

맨 위에 'PDF 해독 라이브러리'라고 말씀 드렸던 라이브러리에서 동작을 합니다.
순서는 아래와 같습니다.

1. 비밀번호를 받아서 파일을 오픈합니다.

// _pdfPath에 있는 데이터를 바이트 단위로 읽고 리스트로 반환합니다.
var pdfDataBytes = File(_pdfPath).readAsBytesSync();

// 위에서 받은 읽어온 파일의 바이트 리스트와 문서의 비밀번호를 받아서 넣습니다.
syncPdf.PdfDocument document 
= syncPdf.PdfDocument(inputBytes: pdfDataBytes, password: _password);

2. 열린 파일의 비밀번호를 제거합니다.

: 한번 사용자가 비밀번호로 열은 파일은 다시 비밀번호를 입력하지 않아도 되도록 하기 permission을 clear 해주는 작업을 거쳤습니다.

syncPdf.PdfSecurity security = document.security;

// 비밀번호로 연 PDF 파일에서 permission을 획득하고 모든 권한을 default로 돌립니다.
security.permissions.clear();

// 그런 뒤에 document를 저장하고 dispose 시켜줍니다.
List<int> bytes = document.save();
document.dispose();

3. 제거된 document를 기존의 파일에 덮어씁니다.

Future<void> _overwriteDecryptPdfFile(List<int> bytes) async {
  String _pdfPath = await macrogenPdfDownloadPath();
  var file = File(_pdfPath);

// flush를 true로 하면 비동기에서 complete를 던져주기 전에 영구파일로 저장하도록 해줍니다.
  await file.writeAsBytes(bytes, flush: true);
}

4. native_pdf_view 의 controller을 생성시켜줍니다.

Future<void> _createPdfController() async {
    String _pdfPath = await macrogenPdfDownloadPath();

    if (_pdfPath.isNotEmpty) {
      _pdfController = PdfController(document: PdfDocument.openFile(_pdfPath));
   }
}

5. 완성 (만일 assets/ 폴더에 pdf 파일이 있을 경우)

: rootBundle.load('assets/파일명') 을 사용해서 파일을 읽어서 바이트 데이터를 리스트로 만들어줍니다.
예)

Future<List<int>> _readDocumentData(String name) async {
  final ByteData data = await rootBundle.load('assets/$name');
  return data.buffer.asUint8List(data.offsetInBytes, data.lengthInBytes);
}

PdfDocument document = PdfDocument(
        inputBytes: await _readDocumentData('result.pdf'), password: '1991');

** buffer flush?
버퍼 플러시는 임시 저장 영역에서 컴퓨터의 영구 메모리로 컴퓨터 데이터를 전송하는 것입니다. 예를 들어 파일을 변경하면 한 컴퓨터 화면에서 볼 수 있는 변경 사항이 일시적으로 버퍼에 저장됩니다.
일반적으로 임시 파일은 워드 문서를 열 때 생성되고 기본 파일을 닫으면 자동으로 소멸됩니다. 따라서 작업을 저장할 때 마지막으로 문서를 저장한 이후 문서에 대한 변경 사항이 버퍼에서 하드 디스크의 영구 저장소로 플러시됩니다.

profile
Android, Flutter 앱 개발자입니다.

0개의 댓글