在Flutter中解密后显示pdf文件的问题

yr9zkbsy  于 2023-10-22  发布在  Flutter
关注(0)|答案(1)|浏览(149)

我正在研究一个Flutter应用程序,它涉及从互联网上获取PDF文件,加密并将其存储在应用程序文件目录中,并检索,解密以在应用程序中显示。我正在使用https://pub.dev/packages/encryptSyncfusion pdf viewer来实现此目的。但是在解密和显示文件时,

ArgumentError{Invalid argument (position): Invalid Position:-1}

在SfPdfViewer中运行调试模式。代码为:

`SfPdfViewer.network( 
          widget.file!.link!, 
          key: _pdfViewerKey, 
          onDocumentLoaded: (PdfDocumentLoadedDetails details) async { 
        // final Directory tempPath = await getApplicationDocumentsDirectory(); 
        // _tempFile = await File('${tempPath.path}/${widget.file!.title}.pdf') 
        //     .writeAsBytes( await details.document.save()); 
      }):FutureBuilder<Uint8List>(
        future: getFileBytes(),
        builder:(context,snapshot){
          if(snapshot.hasData)
          {
            logger.i("Snapshot Data is ${snapshot.data}");
            return SfPdfViewer.memory(snapshot.data!,key: _pdfViewerKey, );
          }
          else if(snapshot.hasData)
          {
            snapshot.printError();
            return Text('Error');
          }
          else
          {
            return const Center(child: CircularProgressIndicator());
          }
        }
      )
      );
    
  }
  Future<Uint8List> getFileBytes() async
  {
    return await fileController.getDecryptedFile(name: widget.file!.title!);
    
  }`

下载、加密和解密的方法有:

Future<void> downloadFile({required Files file})async
  {
    
    logger.e("Link of file to be downloaded is ${file.link}");
    Response response=await download(url: file.link!);
      final directory = await getApplicationDocumentsDirectory();
    final filesDirectory = await Directory('${directory.path}/files').create(recursive: true);
    

    String filePath='${filesDirectory.path}/${file.title!}.aes';

   
    logger.i("Length of key is ${key.length}");
    final encryptor=Encrypter(AES(key,padding: null));
    logger.i("Unencrypted bytes: ${response.data}");
    final encryptedBytes = encryptor.encryptBytes(response.data,iv: iv,);
    final decryptedBytes = encryptor.decryptBytes(encryptedBytes,iv: iv,associatedData: encryptedBytes.bytes);
    logger.i("encrypted bytes: ${encryptedBytes}");
    final encryptedFile=File(filePath);
    encryptedFile.writeAsBytesSync(encryptedBytes.bytes);
    changeDownloadStatus(true);
    
    
  }


  Future<dynamic> download({required String url}) async
{
  try{
    String token=url.substring(url.indexOf("token")+7,url.indexOf("_gl"));
    String alt=url.substring( url.indexOf("alt=")+5,url.indexOf("token="));
    String gl=url.substring(url.indexOf("_gl=")+5);
    Map<String,String> query={
      "token":token,
      "alt":alt,
      "_gl":gl
    };
    Response response =await Dio().get(url.substring(0,url.indexOf("?")),options: Options(responseType: ResponseType.bytes,
            followRedirects: false,contentType: "application/pdf"),queryParameters: query);
    logger.i(response.data);

    changeDownloadStatus(true);
    return response;
  }
  on Exception catch(e)
  {
    logger.e(e.toString());
  }
}

Future<Uint8List> getDecryptedFile({required String name}) async
{
     final directory = await getApplicationDocumentsDirectory();
    final filesDirectory = Directory('${directory.path}/files');
    String filePath='${filesDirectory.path}/$name.aes';
    File encryptedfile=File(filePath);
    bool isPresent=await encryptedfile.exists();
    logger.i("File at path $filePath is present $isPresent");
   
    
      Uint8List encryptedBytes=encryptedfile.readAsBytesSync();
      logger.i("encrypted bytes: ${encryptedBytes}");
      
      // Decrypt the file
      
    final encryptor=Encrypter(AES(key,padding: null));
    final decryptedBytes=encryptor.decryptBytes(Encrypted(encryptedBytes),iv: iv,associatedData: encryptedBytes);

    return Uint8List.fromList(decryptedBytes);
    
   
}

Key和Iv的计算公式如下:

final iv=IV.fromLength(16);
    final key=Key.fromSecureRandom(32);

我得到一个列表中的日志与未加密的字节和解密的字节相同的数据。另外,当在decryptor对象中使用默认填充时,我会得到**解密方法中无效或损坏的填充。**问题在哪里?

raogr8fs

raogr8fs1#

我们已经查看了提供的示例,并创建了一个类似的应用程序,使用您通过https://pub.dev/packages/encrypt共享的包加密和解密文件。我们已经成功地在SfPdfViewer中加载了解密的字节,并且它在我们的终端上正确地显示了PDF文档。我附上了示例的代码片段供您参考。请尝试一下,让我们知道你是否仍然面临任何问题。如果你是,请分享修改后的代码示例,重现问题。这将有助于我们尽快提供及时的解决方案。

验证码:

import 'dart:typed_data';
import 'package:flutter/material.dart';
import 'package:syncfusion_flutter_pdfviewer/pdfviewer.dart';
import 'package:encrypt/encrypt.dart' as encrypt;
import 'package:http/http.dart' as http;

void main() {
  runApp(MaterialApp(
    title: 'Syncfusion PDF Viewer Demo',
    home: HomePage(),
  ));
}

/// Represents Homepage for Navigation
class HomePage extends StatefulWidget {
  @override
  _HomePage createState() => _HomePage();
}

class _HomePage extends State<HomePage> {
  final GlobalKey<SfPdfViewerState> _pdfViewerKey = GlobalKey();
  Uint8List? _documentBytes;

  @override
  void initState() {
    super.initState();
    loadPdfDocument();
  }

  @override
  Widget build(BuildContext context) {
    return Scaffold(
        appBar: AppBar(
          title: const Text('Syncfusion Flutter PDF Viewer'),
        ),
        body: _documentBytes != null
            ? SfPdfViewer.memory(_documentBytes!)
            : Container());
  }

  /// Handling the encryption, decryption and load the document in SfPDfViewer.
  Future<void> loadPdfDocument() async {
    const url =
        'https://cdn.syncfusion.com/content/PDFViewer/flutter-succinctly.pdf';
    final response = await http.get(Uri.parse(url));

    if (response.statusCode == 200) {
      final fileBytes = response.bodyBytes;
      final key = encrypt.Key.fromSecureRandom(32);
      final iv = encrypt.IV.fromSecureRandom(16);
      final encrypter =
          encrypt.Encrypter(encrypt.AES(key, mode: encrypt.AESMode.ctr));

      // Encrypt the file
      final encryptedBytes = encrypter.encryptBytes(
        fileBytes,
        iv: iv,
      );
      // Decrypt the file
      final decryptedBytes = encrypter.decryptBytes(encryptedBytes, iv: iv);
      // For loading the decrypted bytes in SfPdfViewer.
      _documentBytes = Uint8List.fromList(decryptedBytes);
      setState(() {});
    }
  }
}

相关问题