스트림 및 파일 첨부

스트림 및 파일 첨부

스트림 및 파일 첨부

기본 Document.Open/Document.Save 오버로드를 넘어, Aspose.PDF FOSS for .NET는 문서 안팎으로 바이트가 이동하는 방식을 보다 정밀하게 제어할 수 있게 합니다 – 매우 큰 파일을 위한 확장 가능한 인메모리 버퍼와 FileSpecification 및 EmbeddedFileCollection을 통한 파일 첨부의 삽입, 검사, 추출을 위한 전용 API을 제공합니다.


2 GB를 초과하는 인메모리 버퍼 확장

MemoryStream는 데이터를 단일 연속 배열에 저장하므로 약 2 GB 정도로 제한됩니다. 반면 OptimizedMemoryStream는 데이터를 고정 크기 청크로 저장하므로 PDF를 메모리 내에서 완전히 저장하거나 생성할 때 훨씬 더 큰 문서를 보관할 수 있습니다.

using Aspose.Pdf;

using var doc = Document.Open("large-input.pdf");
using var buffer = new OptimizedMemoryStream();

doc.Save(buffer);

buffer.Seek(0, SeekOrigin.Begin);
byte[] allBytes = buffer.ToArray();
Console.WriteLine($"Buffer length: {buffer.Length}");

또한 Stream와 마찬가지로 직접 쓸 수도 있습니다:

using var buffer = new OptimizedMemoryStream();
byte[] chunk = System.Text.Encoding.UTF8.GetBytes("raw content chunk");

buffer.Write(chunk, 0, chunk.Length);
buffer.WriteByte(0x0A);
buffer.SetLength(buffer.Length);

스트림에서 직접 파일 삽입

FileSpecification는 첨부 파일을 먼저 byte[]에 버퍼링하도록 요구하는 대신 Stream을 래핑할 수 있습니다. 이는 첨부 파일 소스 자체가 스트림인 경우, 예를 들어 열린 파일 핸들과 같이, 유용합니다.

using Aspose.Pdf;

using var doc = Document.Open("input.pdf");
using var attachmentStream = File.OpenRead("report.csv");
using var spec = new FileSpecification(attachmentStream, "report.csv", "Quarterly report data");

spec.MimeType = "text/csv";
spec.AFRelationship = AFRelationship.Data;
spec.Encoding = FileEncoding.Zip;

doc.EmbeddedFiles.Add(spec);
doc.Save("with-attachment.pdf");

원시 바이트에서 파일 삽입

Document.AddEmbeddedFile은 바이트 배열에서 직접 파일을 삽입하기 위한 편리한 메서드이며, FileSpecification을 직접 구성하지 않아도 됩니다.

using Aspose.Pdf;

using var doc = Document.Open("input.pdf");
byte[] fileData = File.ReadAllBytes("appendix.docx");

doc.AddEmbeddedFile(
    "appendix.docx",
    fileData,
    "Supporting appendix",
    "application/vnd.openxmlformats-officedocument.wordprocessingml.document",
    true,
    DateTime.Now,
    DateTime.Now);

doc.Save("with-appendix.pdf");

임베드된 파일 열거 및 추출

Document.EmbeddedFiles은 열거할 수 있는 EmbeddedFileCollection입니다. 각 항목은 FileSpecification이며, GetData()은 첨부 파일의 원시 바이트를 반환합니다.

using Aspose.Pdf;

using var doc = Document.Open("with-attachment.pdf");

if (doc.HasEmbeddedFiles)
{
    foreach (FileSpecification file in doc.EmbeddedFiles)
    {
        Console.WriteLine($"{file.Name} ({file.Size} bytes, {file.MimeType})");
        byte[] contents = file.GetData();
        File.WriteAllBytes(file.Name, contents);
    }
}

첨부 파일 찾기, 검사 및 제거

FindByName을 사용하여 단일 첨부 파일을 조회하고, Params으로 메타데이터를 읽으며, Delete/DeleteByKey을 사용해 이를 제거합니다.

using Aspose.Pdf;

using var doc = Document.Open("with-attachment.pdf");

FileSpecification? found = doc.EmbeddedFiles.FindByName("report.csv");
if (found?.Params is FileParams info)
{
    Console.WriteLine($"{found.Name}: {info.Size} bytes, checksum {info.CheckSum}, modified {info.ModDate}");
}

doc.EmbeddedFiles.Delete("report.csv");
Console.WriteLine($"Remaining attachments: {doc.EmbeddedFiles.Count}");
doc.Save("cleaned.pdf");

팁 및 모범 사례

  • 인메모리 문서가 2GB를 초과할 가능성이 있을 때는 MemoryStream보다 OptimizedMemoryStream을 선호하세요 – MemoryStream는 단일 백업 배열이 해당 한도에 도달하면 예외를 발생시킵니다.
  • Dispose FileSpecification 인스턴스(및 해당 인스턴스를 위해 수동으로 연 모든 스트림)를 해제하십시오 – FileSpecification은 IDisposable를 구현합니다.
  • Document.HasEmbeddedFiles을(를) 확인하고 EmbeddedFiles을 반복하기 전에 첨부 파일이 없는 문서에 대한 불필요한 열거를 건너뛰세요.
  • 각 FileSpecification에 MimeType와 AFRelationship을 설정하여 하위 PDF 소비자가 첨부 파일을 올바르게 분류할 수 있도록 하세요.
  • 수동 루프를 작성하는 대신 단일 명명된 조회에 EmbeddedFileCollection.FindByName을 사용하세요.

일반적인 문제

문제원인해결 방법
OutOfMemoryException 큰 문서를 스트림에 저장MemoryStream는 단일 ~2 GB 백업 배열로 제한됩니다대신 OptimizedMemoryStream에 저장
FileSpecification.GetData()가 빈 배열을 반환합니다소스 스트림 위치가 FileSpecification가 생성되기 전에 초기화되지 않았습니다스트림을 위치 0으로 이동시키거나(또는 다시 열어) FileSpecification에 전달하기 전에 수행하십시오
EmbeddedFiles.FindByName는 null를 반환합니다첨부 파일 이름이 정확히 일치하지 않습니다(조회는 이름 기반입니다)doc.EmbeddedFiles를 반복하고 Name 값을 비교하거나 Keys를 확인하십시오
첨부 파일을 삭제하면 잘못된 항목이 제거됩니다여러 첨부 파일이 동일한 이름을 공유하고 있습니다명확한 제거를 위해 Keys의 정확한 키와 함께 DeleteByKey를 사용하십시오

FAQ

MemoryStream와 OptimizedMemoryStream의 차이점은 무엇인가요?

MemoryStream은 바이트를 약 2GB에 가까운 하나의 연속 배열에 저장합니다. OptimizedMemoryStream은 대신 고정 크기 청크로 데이터를 저장하므로 해당 제한을 초과하여 확장할 수 있습니다 – 매우 큰 파일을 메모리 내에서 완전히 처리하는 Document.Save 작업에 유용합니다.

파일을 먼저 byte[]에 로드하지 않고 임베드할 수 있나요?

예. FileSpecification(stream, name, description)은 Stream을 직접 받아들이므로, File.OpenRead(...) 또는 다른 스트림에서 메모리에 직접 버퍼링하지 않고 임베드할 수 있습니다.

문서에서 임베드된 파일을 어떻게 다시 추출하나요?

doc.EmbeddedFiles을 반복하고 각 FileSpecification에 대해 GetData()을 호출하여 원시 바이트를 가져옵니다.

EmbeddedFileCollection.Delete(name) 메서드는 해당 이름을 가진 모든 첨부 파일을 삭제하나요?

아니요 – 동일한 이름을 공유하는 첨부 파일이 여러 개일 경우, DeleteByKey과 Keys에서 제공하는 특정 키를 사용해 정확히 하나의 첨부 파일을 지정하세요.

FileSpecification을 여러 문서에서 재사용해도 안전한가요?

아니요. FileSpecification은 IDisposable을 구현하고 단일 임베드 파일 스트림을 감싸므로, 문서당 첨부 파일마다 새로운 인스턴스를 생성하세요.


API Reference 요약

클래스 / 메서드설명
OptimizedMemoryStream2 GB 제한을 초과하는 MemoryStream의 확장 가능한 인메모리 스트림
OptimizedMemoryStream.Write버퍼에 바이트를 씁니다
OptimizedMemoryStream.ToArray버퍼링된 바이트를 바이트 배열로 반환합니다
FileSpecification스트림 또는 바이트 데이터에 의해 지원되는 임베디드 파일 첨부 설명자
FileSpecification.GetData임베디드 파일의 원시 바이트를 가져오기
FileSpecification.Params임베디드 파일에 대한 메타데이터(크기, 체크섬, 날짜)
EmbeddedFileCollectionDocument에 대한 FileSpecification 첨부 파일 컬렉션
EmbeddedFileCollection.FindByName이름으로 첨부 파일 조회
EmbeddedFileCollection.Delete이름으로 첨부 파일 삭제
Document.AddEmbeddedFile원시 바이트에서 파일을 삽입하기 위한 편리 메서드
Document.EmbeddedFiles문서에 포함된 파일 컬렉션
Document.HasEmbeddedFiles문서에 embedded files가 포함되어 있는지 여부
FileParams임베드된 파일 스트림에 대한 size/checksum/date 메타데이터를 래핑합니다

참조

 한국어