Flutter 应用程序在加密 PDF 或压缩文件时卡住
在我的应用程序中,我使用的是底部工作表,上面有几个小部件。它看起来像这样:
当用户单击“我的文档”时,我将调用 saveToMyDocs 函数,该函数将检查“启用密码”开关是否打开,它将使用提供的密码加密 pdf 文件,如果启用“创建 zip 文件”开关后,它将创建加密文件的 zip。这是我的“saveToMyDocs”功能:
Future saveToMyDocs(BuildContext context, bool savePDF, bool encrypt, String password, bool zip, String sourceFile, String fileName) async {
ProgressDialog pd = ProgressDialog(context: context);
pd.show(max: 100, msg: "Saving file\nPlease wait...", progressBgColor: Color.fromARGB(255, 224, 224, 224), progressValueColor: Color.fromARGB(255, 2, 136, 209));
String sourceFilePath = sourceFile;
Directory appDocDir = await getApplicationDocumentsDirectory();
String tempPath = appDocDir.path;
var now = DateTime.now();
String name = now.day.toString() + now.month.toString() + now.year.toString() + now.hour.toString() + now.minute.toString() + now.second.toString();
String tempFilePath = tempPath + "/" + name;
String destinationFilePath = await ExternalPath.getExternalStoragePublicDirectory(ExternalPath.DIRECTORY_DOCUMENTS);
if (savePDF) {
if (encrypt) {
final PdfDocument document = PdfDocument(inputBytes: File(sourceFilePath).readAsBytesSync());
final PdfSecurity security = document.security;
security.userPassword = password;
security.ownerPassword = password;
security.algorithm = PdfEncryptionAlgorithm.aesx256Bit;
await File(tempFilePath + ".pdf").writeAsBytes(document.save());
document.dispose();
sourceFilePath = tempFilePath + ".pdf";
}
if (zip) {
var encoder = ZipFileEncoder();
encoder.create(tempFilePath + ".zip");
encoder.addFile(File(sourceFilePath));
encoder.close();
sourceFilePath = tempFilePath + ".zip";
}
try {
if (sourceFilePath.endsWith(".pdf")) {
await File(sourceFilePath).rename(destinationFilePath + "/" + fileName + ".pdf");
}
else {
await File(sourceFilePath).rename(destinationFilePath + "/" + fileName + ".zip");
}
} on FileSystemException catch (e) {
if (sourceFilePath.endsWith(".pdf")) {
final newFile = await File(sourceFilePath).copy(destinationFilePath + "/" + fileName + ".pdf");
await File(sourceFilePath).delete();
}
else {
final newFile = await File(sourceFilePath).copy(destinationFilePath + "/" + fileName + ".zip");
await File(sourceFilePath).delete();
}
}
if(pd.isOpen()) {
pd.close();
}
}
}
这一切都工作正常,但问题是,如果启用了任何开关(“启用密码”或“创建 zip”),那么应用程序就会卡住。这意味着,如果启用了这些开关中的任何一个,并且如果我单击调用“saveToMyDocs”的“我的文档”,则不会出现该进度对话框,并且我也无法与底部工作表或任何元素进行交互。进度对话框在很长一段时间后显示,只显示一秒钟,然后突然关闭。加密和创建 zip 文件没有任何错误,但问题是整个应用程序卡住(冻结)。如果这两个开关都关闭,则不会出现问题。并且也没有警告或错误消息。
简而言之,如果整个保存过程需要 n 秒,那么我的应用程序将冻结 ~(n-1) 秒,然后在最后 1 秒内进度对话框将立即打开和关闭。
如果创建 zip 文件并启用密码未启用,那么它可以顺利工作。可能是什么问题。
任何帮助将不胜感激。谢谢。
In my app I am using a Bottom Sheet with few widgets on it. It look like this:
When user clicks on My Documents I am calling a saveToMyDocs function which will check if 'enable password' switch is on, it will encrypt the pdf file with the password provided and if 'create zip file' switch is enabled, it will then create a zip of the encrypted file. Here is my 'saveToMyDocs' function:
Future saveToMyDocs(BuildContext context, bool savePDF, bool encrypt, String password, bool zip, String sourceFile, String fileName) async {
ProgressDialog pd = ProgressDialog(context: context);
pd.show(max: 100, msg: "Saving file\nPlease wait...", progressBgColor: Color.fromARGB(255, 224, 224, 224), progressValueColor: Color.fromARGB(255, 2, 136, 209));
String sourceFilePath = sourceFile;
Directory appDocDir = await getApplicationDocumentsDirectory();
String tempPath = appDocDir.path;
var now = DateTime.now();
String name = now.day.toString() + now.month.toString() + now.year.toString() + now.hour.toString() + now.minute.toString() + now.second.toString();
String tempFilePath = tempPath + "/" + name;
String destinationFilePath = await ExternalPath.getExternalStoragePublicDirectory(ExternalPath.DIRECTORY_DOCUMENTS);
if (savePDF) {
if (encrypt) {
final PdfDocument document = PdfDocument(inputBytes: File(sourceFilePath).readAsBytesSync());
final PdfSecurity security = document.security;
security.userPassword = password;
security.ownerPassword = password;
security.algorithm = PdfEncryptionAlgorithm.aesx256Bit;
await File(tempFilePath + ".pdf").writeAsBytes(document.save());
document.dispose();
sourceFilePath = tempFilePath + ".pdf";
}
if (zip) {
var encoder = ZipFileEncoder();
encoder.create(tempFilePath + ".zip");
encoder.addFile(File(sourceFilePath));
encoder.close();
sourceFilePath = tempFilePath + ".zip";
}
try {
if (sourceFilePath.endsWith(".pdf")) {
await File(sourceFilePath).rename(destinationFilePath + "/" + fileName + ".pdf");
}
else {
await File(sourceFilePath).rename(destinationFilePath + "/" + fileName + ".zip");
}
} on FileSystemException catch (e) {
if (sourceFilePath.endsWith(".pdf")) {
final newFile = await File(sourceFilePath).copy(destinationFilePath + "/" + fileName + ".pdf");
await File(sourceFilePath).delete();
}
else {
final newFile = await File(sourceFilePath).copy(destinationFilePath + "/" + fileName + ".zip");
await File(sourceFilePath).delete();
}
}
if(pd.isOpen()) {
pd.close();
}
}
}
This all works fine, but the problem is, if any of the switches ('enable password' or 'create zip') is enabled then the app stucks. It means if any of these switches is enabled and if I click on 'My Documents' which calls 'saveToMyDocs' then that progress dialog does not appear and I can't interact with my bottom sheet or any elements either. The progress dialog shows up after a long time and just for a second and then closes suddenly. The encryption and creating zip file is carried out without any error but the whole app stucks (freezes) is the problem. The problem won't arise if both of these switches are off. And there is no warning or error message either.
In simple words if the whole saving process takes n seconds then my app will freeze for ~(n-1)seconds and then in the last 1 second the progress dialog will open and close instantly.
If create zip file and enable password is not enabled then it works smoothly. What could be the problem.
Any help would be much appreciated. Thank you.
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。
绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(1)
这里的实际问题是
行中的 document.save()
await File(tempPath + "/" + fileName + ".pdf").writeAsBytes(document.save()); 如果您尝试单独编写它,
它将是字节列表。这意味着您的输入文件以字节为单位转换到内存中,而不是存储在存储中的文件中,这就是您的用户界面冻结的原因。我想 zip 也发生了类似的事情。到目前为止,我认为没有任何解决方案,因为将字节保存在存储中需要时间,并且库的主要部分必须重新写入。
要创建 zip 文件,您可以使用“flutter_archive”。只需添加:
在 pubsec.yaml 中,然后运行 pub get 现在您可以像这样导入它:
要创建 zip 文件,您可以使用以下代码:
这里第一行采用一个目录,其中包含所有要存档的文件。
注意:所有文件应位于同一目录中。
之后文件= [];获取要添加到存档中的文件列表。
最后 final zipFile = File("zip_file_path"); 是存储存档的位置。
如果您愿意,可以在其官方页面上阅读有关此包的更多信息 https://pub.dev/packages/flutter_archive< /a>
对于加密部分我会尽快想出解决方案。
The actual problem here is
document.save() in line
await File(tempPath + "/" + fileName + ".pdf").writeAsBytes(document.save());
If you try to write it separately it'll be list of bytes. Meaning your input file is converted in bytes into the memory and not in a file in storage which is the reason while your ui freezes. I guess something similar is happening for the zip as well. As of now I don't think there is any solution to this because for the bytes to be saved in storage instead would take time and major portion of the library has to be written again.
For creating zip files you can use "flutter_archive" instead. Just add:
in your pubsec.yaml and then run pub get and now you can import it like this:
And to create zip file you can use the following code:
Here first line takes a directory in which all the files to be archived are present.
NOTE: All files should be present in the same directory.
After that files = []; takes list of files to be added to the archive.
And finally final zipFile = File("zip_file_path"); is the place where your archive will be stored.
If you want you can read more about this package on its official page https://pub.dev/packages/flutter_archive
For the encryption part I will try to come up for a solution as soon as possible.