powered by simpleCommunicator - 2.0.34     © 2025 Programmizd 02
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / избавиться от MemoryStream
6 сообщений из 6, страница 1 из 1
избавиться от MemoryStream
    #40105229
vb_sub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Всем привет, у меня есть метод, который тянет из MS SQL несколько pdf потоком в виде VarBinary, с помощью PDFSharp все склеивается в один pdf.
Код: c#
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.
52.
53.
54.
55.
56.
57.
58.
public async Task<Stream> GetFileByStream(int id)
        {
            try
            {       
                PdfDocument outputPDFDocument = new PdfDocument();

                await foreach (var stream in getStreams())
                {
                    using PdfDocument inputPDFDocument = PdfReader.Open(stream, PdfDocumentOpenMode.Import);
                    outputPDFDocument.Version = inputPDFDocument.Version;

                    foreach (PdfPage page in inputPDFDocument.Pages)
                        outputPDFDocument.AddPage(page);
                }

                Stream pdfStream = new MemoryStream();
                    outputPDFDocument.Save(pdfStream);
                return pdfStream;
            }
            catch (Exception ex)
            {
                throw;
            }
                     
            async  IAsyncEnumerable<Stream> getStreams()
            {  
                using (SqlConnection connection = new SqlConnection(_connectionString))
                {
                    await connection.OpenAsync();
                    using (SqlCommand command = new SqlCommand(@" select pdffile.fileContent from pdffile
                    where insertedTaskId = @id", connection))
                    {
                        command.Parameters.AddWithValue("id", id);
                        using (SqlDataReader reader = await command.ExecuteReaderAsync(CommandBehavior.SequentialAccess))
                        {                            
                            while (await reader.ReadAsync())
                            {
                                if (!(await reader.IsDBNullAsync(0)))
                                {
                                    using (Stream data = reader.GetStream(0))
                                    {
                                        using var memoryStream = new MemoryStream();
                                        await data.CopyToAsync(memoryStream);
                                        yield return memoryStream;
                                    }
                                }
                            }
                        }
                    }
                }
            }
        } 

    public async Task<IActionResult> GetPdfByTaskFromStreamAsync([FromQuery] int id)
    {
       var result= await _PdfFileRepository.GetFileByStream(id);
       return new FileStreamResult(result, "application/octet-stream") { FileDownloadName = "file.pdf" };
    }


Проблема в том, что мне приходится использовать оберточный MemoryStream, который нормально так отжирает память-хотелось бы избавиться от него. Причем объем потребления памяти увеличивается непропорционально размеру файлов. То есть если нужно из базы получить 10 файлов по 1 Мб и склеить его в один файл 10 мб, то метод отъедает +150 мб Ram.
Если не использовать MemoryStream, а сразу возвращать
Код: c#
1.
Stream data = reader.GetStream(0)


, то при инициализации Pdf-документа
Код: c#
1.
using PdfDocument inputPDFDocument = PdfReader.Open(stream, PdfDocumentOpenMode.Import);

, получаю Exception "Specified method is not supported". Это происходит при попытке получить PdfReader SqlSequentialStream.GetLenght(). Это из-за того, что SqlSequentialStream Not Seekable и не имеет длины.
Вот собственно вопрос- как можно зарефактрить?
Спасибо
...
Рейтинг: 0 / 0
избавиться от MemoryStream
    #40105263
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vb_sub,

можно заменить MemoryStream на RecyclableMemoryStream - авторы (то бишь майкрософт) обещают от этого кучу профитов:

  • Eliminate Large Object Heap allocations by using pooled buffers
  • Incur far fewer gen 2 GCs, and spend far less time paused due to GC
  • Avoid memory leaks by having a bounded pool size
  • Avoid memory fragmentation
  • Allow for multiple ways to read and write data that will avoid extraneous allocations
  • Provide excellent debuggability and logging
  • Provide metrics for performance tracking
...
Рейтинг: 0 / 0
избавиться от MemoryStream
    #40105308
vb_sub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Сон Веры Павловны,
пробовал эту тему- на мое удивление с ним стало только хуже.
...
Рейтинг: 0 / 0
избавиться от MemoryStream
    #40105310
Сон Веры Павловны
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vb_sub
Сон Веры Павловны,
пробовал эту тему- на мое удивление с ним стало только хуже.

Ну тогда, если для PdfReader нужен только размер данных потока, получать этот размер в запросе (функция datalength), и написать свою обёртку, реализующую Stream, и читающую данные мелкими блоками.
А если нужен действительно полноценный seekable stream, то тут от хранения всего содержимого бинарного поля на клиенте не отвертеться никак.
...
Рейтинг: 0 / 0
избавиться от MemoryStream
    #40105360
vb_sub
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
Печально
...
Рейтинг: 0 / 0
избавиться от MemoryStream
    #40108738
Фотография pation
Скрыть профиль Поместить в игнор-лист Сообщения автора в теме
Участник
vb_sub,

using
...
Рейтинг: 0 / 0
6 сообщений из 6, страница 1 из 1
Форумы / WinForms, .Net Framework [игнор отключен] [закрыт для гостей] / избавиться от MemoryStream
Целевая тема:
Создать новую тему:
Автор:
Закрыть
Цитировать
Найденые пользователи ...
Разблокировать пользователей ...
Читали форум (0):
Пользователи онлайн (0):
x
x
Закрыть


Просмотр
0 / 0
Close
Debug Console [Select Text]