기술 문서

PDFium 구성 요소를 사용하여 Delphi에서 PDF 첨부 파일 작업

· PDF 프로그래밍

PDF 문서는 포함된 파일 첨부 기능을 가지고 있으며, 이는 스프레드시트, 이미지 또는 관련 문서와 같은 파일을 묶는 데 유용한 기능입니다. 첨부 파일 데모는 PDFium VCL을 사용하여 PDF 첨부 파일을 처리하는 방법을 보여줍니다.

개요

이 데모는 PDF 문서에서 첨부 파일을 나열, 추출, 추가 및 삭제하는 등 완전한 첨부 파일 관리 기능을 제공합니다. 복잡한 PDF 파일을 처리해야 하는 문서 관리 시스템에 필수적입니다.

주요 기능

  • 첨부 파일 목록 – PDF에 포함된 모든 파일을 확인합니다.
  • 첨부 파일 추출 – 첨부 파일을 디스크에 저장합니다.
  • 첨부 파일 추가 – PDF 파일에 새 파일 삽입
  • 첨부 파일 삭제 – PDF 파일에서 첨부 파일 제거
  • 세부 정보 보기 – 첨부 파일 이름 및 크기 확인

PDFium DLL 요구 사항

PDFium VCL 애플리케이션을 실행하기 전에, PDFium DLL 파일이 설치되어 있는지 확인하십시오.

  • pdfium32.dll / pdfium64.dll – 표준 버전 (약 5-6 MB)
  • pdfium32v8.dll / pdfium64v8.dll – V8 JavaScript 엔진 포함 (약 23-27 MB)

설치: 실행 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 양식을 처리하든, 이러한 API를 사용하면 쉽게 구현할 수 있습니다.

프로그래밍 방식으로 첨부 파일을 추가, 추출 및 삭제하는 기능은 문서 자동화 및 처리 워크플로우에 다양한 가능성을 제공합니다.

PDF 첨부 파일 관리 쉽게 사용하세요. Delphi PDFium VCL.