itext7 возвращает большой PDF с сервера - PullRequest
0 голосов
/ 15 января 2020

У меня проблема с iText7 и. NET Core 3.

В моей базе данных есть куча PDF-файлов, и случай использования заключается в том, что каждые несколько дней кто-то должен получать эти файлы как один большой PDF-файл. Проблема в том, что когда ядро ​​asp. net выделяет память для этого файла PDF (~ 50 МБ), оно не освобождает ее. Насколько я знаю, он расположен на куче больших объектов, которые не GCed. Проблема в том, что приложение начинает генерировать исключения OutOfMemory. Итак, я прошу руководство от c# byte [] guru =) Я написал свой код так:

public virtual async Task<ResultEntity> CreateDocument(CancellationToken ct, List<DocEntity> entities)
    {
        var result = new ResultEntity();

        var resultBytes = await base.CreateDocumentA4(async (pdfDoc, doc, ms) =>
        {
            var merger = new PdfMerger(pdfDoc);

            foreach (var entity in entities)
            {
                PrintEntity print = null;

                // removed for readability

                if (print != null)
                {
                    MergePdfDocument(merger, print.Bytes );
                }

                Current++;
                await UpdateProgress();
            }
        }, ct);

        result.Bytes = resultBytes;

        return result;
    }

Базовая реализация выглядит следующим образом:

 private async Task<byte[]> CreateDocument(Func<PdfDocument, Document, PdfWriter, Task> operation,
        PageSize pageSize, CancellationToken ct)
    {
        var wProps = new WriterProperties();
        wProps.SetPdfVersion(PdfVersion.PDF_2_0);
        wProps.SetFullCompressionMode(true);

        using (var ms = new MemoryStream())
        using (var w = new PdfWriter(ms, wProps))
        using (var pdfDoc = new PdfDocument(w))
        {
            pdfDoc.SetDefaultPageSize(pageSize);
            AddDocMeta(pdfDoc);

            ct.ThrowIfCancellationRequested();

            using (var doc = new Document(pdfDoc, pageSize))
            {
                await operation(pdfDoc, doc, w);
                doc.Close();
            }

            pdfDoc.Close();
            return ms.ToArray();
        }
    }

    public static void MergePdfDocument(PdfMerger merger, byte[] documentSource)
    {
        var iRandomSrc = new RandomAccessSourceFactory().CreateSource(documentSource);
        using (var reader = new PdfReader(iRandomSrc, new ReaderProperties()))
        using (var src = new PdfDocument(reader))
        {
            merger.Merge(src, 1, src.GetNumberOfPages());
            src.Close();
        }
    }

И в. net ядро ​​Я использую пользовательский OutputFormatter, например, так:

    public override async Task WriteResponseBodyAsync(OutputFormatterWriteContext context)
    {
        var docEntity = (DocumentEntity) context.Object;

        if (docEntity.DocumentBytes == null)
        {
            docEntity.DocumentBytes = Array.Empty<byte>();
        }

        var response = context.HttpContext.Response;

        var contentDisposition = new ContentDispositionHeaderValue("attachment");

        if (!string.IsNullOrWhiteSpace(docEntity.Format))
        {
            switch (docEntity.Format.ToLower())
            {
                case "pdf":
                case "xls":
                    contentDisposition.SetHttpFileName(docEntity.FileName.ToLower() + "." +
                                                       docEntity.Format.ToLower());
                    break;
            }
        }

        response.Headers[HeaderNames.ContentDisposition] = contentDisposition.ToString();
        response.ContentLength = docEntity.DocumentBytes.LongLength;

        using (docEntity)
        {
            await response.Body.WriteAsync(docEntity.DocumentBytes, 0, docEntity.DocumentBytes.Length);
        }
    }

Так, что я делаю не так? Как мне освободить те надоедливые байты, которые были выделены? Заранее спасибо.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...