مقالة تقنية

العمل مع مرفقات PDF في دلفي باستخدام مكون PDFium

· برمجة PDF

يمكن أن تحتوي مستندات PDF على ملفات مرفقة مضمنة - وهي ميزة قوية لتجميع الملفات ذات الصلة مثل جداول البيانات والصور أو المستندات الداعمة. المرفقات يوضح العرض التوضيحي كيفية العمل مع المرفقات في PDF باستخدام PDFium VCL.

نظرة عامة

يوفر هذا العرض التوضيحي إدارة كاملة للمرفقات بما في ذلك القائمة والاستخراج والإضافة والحذف من مستندات PDF. إنه ضروري لأنظمة إدارة المستندات التي تحتاج إلى التعامل مع ملفات PDF معقدة.

الميزات الرئيسية

  • قائمة المرفقات - عرض جميع الملفات المضمنة في PDF.
  • استخراج المرفقات - حفظ المرفقات على القرص.
  • إضافة مرفقات. – تضمين ملفات جديدة في ملفات PDF.
  • حذف مرفقات. – إزالة المرفقات من ملفات PDF.
  • عرض التفاصيل. – عرض أسماء وأحجام المرفقات.

متطلبات ملف PDFium DLL.

قبل تشغيل أي تطبيق PDFium VCL، تأكد من تثبيت ملفات PDFium DLL:

  • pdfium32.dll / pdfium64.dll – الإصدارات القياسية (حوالي 5-6 ميجابايت).
  • pdfium32v8.dll / pdfium64v8.dll – مع محرك JavaScript V8 (حوالي 23-27 ميجابايت).

التثبيت: تشغيل PDFiumVCL\DLLs\CopyDlls.bat بصلاحيات المسؤول لنسخ ملفات DLL تلقائيًا إلى مجلدات نظام Windows.

قائمة المرفقات.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
procedure TFormMain.RefreshAttachmentList;
var
  I: Integer;
  AttachmentName: string;
  AttachmentData: TBytes;
  SizeStr: string;
begin
  ListBoxAttachments.Items.Clear;
  
  if not Pdf.Active then
    Exit;
    
  for I := 0 to Pdf.AttachmentCount - 1 do
  begin
    AttachmentName := Pdf.AttachmentName[I];
    AttachmentData := Pdf.Attachment[I];
    
    // Format size
    if Length(AttachmentData) >= 1024 * 1024 then
      SizeStr := Format('%.2f MB', [Length(AttachmentData) / (1024 * 1024)])
    else if Length(AttachmentData) >= 1024 then
      SizeStr := Format('%.2f KB', [Length(AttachmentData) / 1024])
    else
      SizeStr := Format('%d bytes', [Length(AttachmentData)]);
      
    ListBoxAttachments.Items.Add(Format('%s (%s)', [AttachmentName, SizeStr]));
  end;
  
  LogStatus(Format('Found %d attachment(s)', [Pdf.AttachmentCount]));
end;

استخراج المرفقات.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
procedure TFormMain.ButtonExtractAttachmentClick(Sender: TObject);
var
  Index: Integer;
  AttachmentName: string;
  AttachmentData: TBytes;
  FileStream: TFileStream;
begin
  Index := GetSelectedAttachmentIndex;
  if Index < 0 then
  begin
    LogStatus('Please select an attachment to extract.');
    Exit;
  end;
  
  try
    AttachmentName := Pdf.AttachmentName[Index];
    AttachmentData := Pdf.Attachment[Index];
    
    SaveDialog.FileName := AttachmentName;
    if SaveDialog.Execute then
    begin
      FileStream := TFileStream.Create(SaveDialog.FileName, fmCreate);
      try
        if Length(AttachmentData) > 0 then
          FileStream.WriteBuffer(AttachmentData[0], Length(AttachmentData));
          
        LogStatus('Extracted: ' + SaveDialog.FileName);
      finally
        FileStream.Free;
      end;
    end;
    
  except
    on E: Exception do
      LogStatus('Error extracting attachment: ' + E.Message);
  end;
end;

إضافة مرفقات.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
procedure TFormMain.ButtonAddAttachmentClick(Sender: TObject);
var
  AttachmentName: string;
  FileData: TBytes;
  FileStream: TFileStream;
begin
  if not Pdf.Active then
  begin
    LogStatus('Please load or create a PDF document first.');
    Exit;
  end;
  
  OpenDialog.Filter := 'All Files|*.*';
  if OpenDialog.Execute then
  begin
    try
      // Read file into byte array
      FileStream := TFileStream.Create(OpenDialog.FileName, fmOpenRead);
      try
        SetLength(FileData, FileStream.Size);
        if FileStream.Size > 0 then
          FileStream.ReadBuffer(FileData[0], FileStream.Size);
      finally
        FileStream.Free;
      end;
      
      // Use filename as attachment name
      AttachmentName := ExtractFileName(OpenDialog.FileName);
      
      // Create attachment slot
      if Pdf.CreateAttachment(AttachmentName) then
      begin
        // Find the new attachment and set its data
        Pdf.Attachment[Pdf.AttachmentCount - 1] := FileData;
        
        LogStatus('Added attachment: ' + AttachmentName);
        RefreshAttachmentList;
      end
      else
        LogStatus('Failed to create attachment: ' + AttachmentName);
        
    except
      on E: Exception do
        LogStatus('Error adding attachment: ' + E.Message);
    end;
  end;
end;

حذف مرفقات.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
procedure TFormMain.ButtonDeleteAttachmentClick(Sender: TObject);
var
  Index: Integer;
  AttachmentName: string;
begin
  Index := GetSelectedAttachmentIndex;
  if Index < 0 then
  begin
    LogStatus('Please select an attachment to delete.');
    Exit;
  end;
  
  try
    AttachmentName := Pdf.AttachmentName[Index];
    
    if MessageDlg(Format('Delete attachment "%s"?', [AttachmentName]),
      mtConfirmation, [mbYes, mbNo], 0) = mrYes then
    begin
      if Pdf.DeleteAttachment(Index) then
      begin
        LogStatus('Deleted attachment: ' + AttachmentName);
        RefreshAttachmentList;
      end
      else
        LogStatus('Failed to delete attachment.');
    end;
    
  except
    on E: Exception do
      LogStatus('Error deleting attachment: ' + E.Message);
  end;
end;

الوصول إلى خصائص المرفقات.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
// Number of attachments
Count := Pdf.AttachmentCount;
 
// Attachment name at index
Name := Pdf.AttachmentName[Index];
 
// Attachment data as byte array
Data := Pdf.Attachment[Index];
 
// Set attachment data
Pdf.Attachment[Index] := NewData;
 
// Create new attachment
Success := Pdf.CreateAttachment('filename.txt');
 
// Delete attachment
Success := Pdf.DeleteAttachment(Index);

إنشاء مستند جديد مع مرفقات.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
procedure CreatePdfWithAttachments;
var
  Pdf: TPdf;
  FileData: TBytes;
  FileStream: TFileStream;
begin
  Pdf := TPdf.Create(nil);
  try
    // Create new document
    Pdf.CreateDocument;
    Pdf.Active := True;
    
    // Add a page
    Pdf.AddPage(1, 595, 842);
    Pdf.PageNumber := 1;
    Pdf.AddText('Document with Attachments', 'Arial', 18, 50, 750,
      clBlack, $FF, 0.0);
    
    // Add first attachment
    FileStream := TFileStream.Create('data.csv', fmOpenRead);
    try
      SetLength(FileData, FileStream.Size);
      FileStream.ReadBuffer(FileData[0], FileStream.Size);
    finally
      FileStream.Free;
    end;
    
    if Pdf.CreateAttachment('data.csv') then
      Pdf.Attachment[0] := FileData;
      
    // Add second attachment
    FileStream := TFileStream.Create('readme.txt', fmOpenRead);
    try
      SetLength(FileData, FileStream.Size);
      FileStream.ReadBuffer(FileData[0], FileStream.Size);
    finally
      FileStream.Free;
    end;
    
    if Pdf.CreateAttachment('readme.txt') then
      Pdf.Attachment[1] := FileData;
      
    // Save
    Pdf.SaveAs('document_with_attachments.pdf');
    
  finally
    Pdf.Active := False;
    Pdf.Free;
  end;
end;

حفظ المستند بعد التعديلات.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
procedure TFormMain.ButtonSaveDocumentClick(Sender: TObject);
var
  CurrentFileName, TempFileName: string;
  WasActive: Boolean;
begin
  SaveDialog.Filter := 'PDF Files|*.pdf|All Files|*.*';
  SaveDialog.DefaultExt := 'pdf';
  
  if SaveDialog.Execute then
  begin
    try
      CurrentFileName := Pdf.FileName;
      WasActive := Pdf.Active;
      
      // If saving to the same file, use temporary file
      if WasActive and SameText(CurrentFileName, SaveDialog.FileName) then
      begin
        TempFileName := SaveDialog.FileName + '.tmp';
        
        if Pdf.SaveAs(TempFileName) then
        begin
          // Close, delete old, rename new
          Pdf.Active := False;
          
          if DeleteFile(CurrentFileName) then
          begin
            if RenameFile(TempFileName, SaveDialog.FileName) then
            begin
              // Reload
              Pdf.FileName := SaveDialog.FileName;
              Pdf.Active := True;
              LogStatus('Document saved successfully.');
            end;
          end;
        end;
      end
      else
      begin
        // Save to different file
        if Pdf.SaveAs(SaveDialog.FileName) then
          LogStatus('Document saved: ' + ExtractFileName(SaveDialog.FileName))
        else
          LogStatus('Failed to save document.');
      end;
      
    except
      on E: Exception do
        LogStatus('Error saving document: ' + E.Message);
    end;
  end;
end;

عرض تفاصيل المرفق.

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
procedure TFormMain.ListBoxAttachmentsClick(Sender: TObject);
var
  Index: Integer;
  AttachmentName: string;
  AttachmentData: TBytes;
begin
  Index := GetSelectedAttachmentIndex;
  
  if Index >= 0 then
  begin
    AttachmentName := Pdf.AttachmentName[Index];
    AttachmentData := Pdf.Attachment[Index];
    
    MemoDetails.Lines.Clear;
    MemoDetails.Lines.Add('Name: ' + AttachmentName);
    MemoDetails.Lines.Add('Size: ' + IntToStr(Length(AttachmentData)) + ' bytes');
    MemoDetails.Lines.Add('Index: ' + IntToStr(Index));
    
    // Try to detect file type from extension
    if EndsText('.txt', AttachmentName) or
       EndsText('.csv', AttachmentName) then
      MemoDetails.Lines.Add('Type: Text file')
    else if EndsText('.pdf', AttachmentName) then
      MemoDetails.Lines.Add('Type: PDF document')
    else if EndsText('.jpg', AttachmentName) or
            EndsText('.png', AttachmentName) then
      MemoDetails.Lines.Add('Type: Image file')
    else
      MemoDetails.Lines.Add('Type: Binary file');
  end;
end;

حالات الاستخدام.

  • حزم المستندات. - تجميع المستند الرئيسي مع الملفات المرفقة.
  • نماذج الإرسال. - قم بإرفاق الأدلة أو المستندات الداعمة بالنماذج.
  • الأدلة الفنية. - قم بتضمين ملفات CAD، وجداول البيانات، أو التعليمات البرمجية المصدر.
  • المستندات القانونية. - قم بإرفاق المرفقات والملاحق.
  • إدارة الأرشيف. - استخراج المرفقات للمعالجة.

الخلاصة.

يوضح نموذج المرفقات كيفية توفير PDFium VCL تحكمًا كاملاً في مرفقات ملفات PDF. سواء كنت تقوم ببناء نظام لإدارة المستندات أو معالجة نماذج PDF تحتوي على ملفات مضمنة، فإن هذه واجهات برمجة التطبيقات (APIs) تجعل الأمر بسيطًا.

تتيح القدرة على إضافة واستخراج وحذف المرفقات برمجيًا العديد من الإمكانيات لأتمتة سير العمل ومعالجة المستندات.

إدارة مرفقات PDF. بسهولة باستخدام. Delphi PDFium VCL..