abhay0648 / pdf_merger

A new Flutter plugin for merge List of PDF files. It supports both android and IOS.
https://pub.dev/packages/pdf_merger
MIT License
6 stars 26 forks source link

Remove hidden duplicate resource from merged pdfs such as font & images #1

Closed bluntmess closed 1 year ago

bluntmess commented 3 years ago

Describe the bug Hidden duplicate resources such as images and fonts in pdfs are not getting removed while merging pdf files.

To Reproduce When I split a sample pdf into single pages and then re-merge them using this plugin then the resultant pdf size is much larger than the original pdf file.

Expected behavior Now it would be great if this plugin can remove find and remove those hidden duplicate resources from the merged pdf file.

Screenshots Merged vs original: Screenshot 2021-06-19 115243

Smartphone (please complete the following information):

abhay0648 commented 3 years ago

@brightseagit PDF merger store file in location provide by path provider and ExtStorage.

 Future<String> getFilePath(String fileStartName) async {
    String path;
    if (GetPlatform.isIOS) {
      Directory appDocDir = await getApplicationDocumentsDirectory();
      path = appDocDir.path;
    } else if (GetPlatform.isAndroid) {
      path = await ExtStorage.getExternalStoragePublicDirectory(
          ExtStorage.DIRECTORY_DOWNLOADS);
    }

    return path + "/" + fileStartName + "ABCEFG5" + ".pdf";
  }

You can change location to TemporaryDirectory

 Future<String> getFilePath(String fileStartName) async {
    String path;
      Directory appDocDir = await getTemporaryDirectory();
      path = appDocDir.path;

    return path + "/" + fileStartName + "ABCEFG5" + ".pdf";
  }

or can use Specific folder to for converting your PDF and remove after you get success;

When you creating PDF from Image you can use compression to

 CreatePDFFromMultipleImageResponse response  = PdfMerger.createPDFFromMultipleImage(paths: filesPath, outputDirPath: outputDirPath, maxWidth : "your width", maxHeight : "your height" , needImageCompressor : true  );

When you creating Image from PDF

CreateImageFromPDFResponse response  = await PdfMerger.createImageFromPDF(path: singleFile, outputDirPath: outputDirPath, maxWidth : "your width", maxHeight : "your height" , createOneImage : true);

Or you can create you custom class where you can manage when temporary folder and when need storage

class FilePathPDF{
  Future<String> getFilePath(String fileStartName, {bool isPDFMerger = false, extension = ".pdf"}) async {
    String path;
    Directory appDocDir;
    if (GetPlatform.isIOS) {
      if(isPDFMerger) {
        appDocDir = await getTemporaryDirectory();
        if(appDocDir == null){
          appDocDir = await getApplicationDocumentsDirectory();
        }
      }
      else
        appDocDir = await getApplicationDocumentsDirectory();
      print(appDocDir.path);
      path = appDocDir.path;
    } else {
      print(isPDFMerger);
      if(isPDFMerger) {
        appDocDir = await getTemporaryDirectory();
        if(appDocDir == null){
          String pathGet = await ExtStorage.getExternalStoragePublicDirectory(ExtStorage.DIRECTORY_DOWNLOADS);
          path = pathGet;
        }else{
          path = appDocDir.path;
        }
      }
      else{
        String pathGet = await ExtStorage.getExternalStoragePublicDirectory(ExtStorage.DIRECTORY_DOWNLOADS);
        print(pathGet);
        if(pathGet == null) {
          appDocDir = await getTemporaryDirectory();
          path = pathGet;
        }else {
          path = pathGet;
        }
      }
    }
    print(path);

    return path +
        "/" +
        fileStartName +
        Utils().getCurrentDateForFileDownload() +
        (extension ?? ".pdf");
  }
}
class Utils {
  String getCurrentDateForFileDownload() {
    var now = new DateTime.now();
    var dateFormatted = DateFormat("yyyy_MM_ddTHH_mm_ss").format(now);

    return dateFormatted;
  }

}
bluntmess commented 3 years ago

Hello, thanks for replying. And sorry that I'm responding late.

I have tried creating Image from PDF with "createOneImage : false" but I failed to do so due to the following error, it only worked with "createOneImage : true" .

D/PdfDroid(25571): PdfDocument.nativeOpen(): return handle = 0xc2aabef0 D/PdfDroid(25571): PdfPage.nativeOpenPage(): return handle = 0xc2a975f0 D/PdfDroid(25571): PdfView(0xbc77ad6c).nativeCreateView(0xc2aabef0, 0xc2a975f0) D/PdfDroid(25571): Matrix: 0.588235 0.000000 0.000000 -0.454545 0.000000 360.000000 D/PdfDroid(25571): Viewbox: 0 0 360 360 D/PdfDroid(25571): doing the rendering... W/System (25571): A resource failed to call close. D/PdfDroid(25571): Converting image buffer pixel order W/aster_null_saf(25571): JNI critical lock held for 18.555ms on Thread[4,tid=25640,Runnable,Thread*=0xe798d210,peer=0x12e40c08,"DefaultDispatcher-worker-1"] D/PdfDroid(25571): PdfView.nativeCreateView() done W/System.err(25571): java.io.FileNotFoundException: /storage/emulated/0/Android/data/com0.example: open failed: EACCES (Permission denied) W/System.err(25571): at libcore.io.IoBridge.open(IoBridge.java:492) W/System.err(25571): at java.io.FileOutputStream.(FileOutputStream.java:236) W/System.err(25571): at java.io.FileOutputStream.(FileOutputStream.java:125) W/System.err(25571): at com.ril.pdf_merger.CreateImageFromPDF$create$pdfFromMultipleImage$1.invokeSuspend(CreateImageFromPDF.kt:65) W/System.err(25571): at kotlin.coroutines.jvm.internal.BaseContinuationImpl.resumeWith(ContinuationImpl.kt:33) W/System.err(25571): at kotlinx.coroutines.DispatchedTask.run(DispatchedTask.kt:56) W/System.err(25571): at kotlinx.coroutines.scheduling.CoroutineScheduler.runSafely(CoroutineScheduler.kt:561) W/System.err(25571): at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.executeTask(CoroutineScheduler.kt:727) W/System.err(25571): at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.runWorker(CoroutineScheduler.kt:667) W/System.err(25571): at kotlinx.coroutines.scheduling.CoroutineScheduler$Worker.run(CoroutineScheduler.kt:655) W/System.err(25571): Caused by: android.system.ErrnoException: open failed: EACCES (Permission denied) W/System.err(25571): at libcore.io.Linux.open(Native Method) W/System.err(25571): at libcore.io.ForwardingOs.open(ForwardingOs.java:166) W/System.err(25571): at libcore.io.BlockGuardOs.open(BlockGuardOs.java:254) W/System.err(25571): at libcore.io.ForwardingOs.open(ForwardingOs.java:166) W/System.err(25571): at android.app.ActivityThread$AndroidOs.open(ActivityThread.java:7542) W/System.err(25571): at libcore.io.IoBridge.open(IoBridge.java:478) W/System.err(25571): ... 9 more I/flutter (25571): Size(43.0, 75.0) I/flutter (25571): [/storage/emulated/0/Android/data/com0.example] I/flutter (25571): Processed successfully