Как я архивирую на лету и поток к Ответу. Вывод в режиме реального времени?

Пусть реализуемая очередь - это q, а стеки, используемые для реализации q, - это stack1 и stack2.

q можно реализовать в двумя способами:

Метод 1 (сделав операцию enQueue дорогостоящей)

Этот метод делает убедитесь, что вновь введенный элемент всегда находится на вершине стека 1, так что операция deQueue просто появляется из stack1. Чтобы поместить элемент в верхнюю часть stack1, используется stack2.

enQueue(q, x)
1) While stack1 is not empty, push everything from stack1 to stack2.
2) Push x to stack1 (assuming size of stacks is unlimited).
3) Push everything back to stack1.
deQueue(q)
1) If stack1 is empty then error
2) Pop an item from stack1 and return it.

Метод 2 (Делая операцию deQueue дорогостоящей)

В этом методе при работе в очереди новый элемент вводится в верхней части стека1. В операции удаления очереди, если стек2 пуст, тогда все элементы перемещаются в стек2 и, наконец, возвращается верхняя часть стека 2.

enQueue(q,  x)
 1) Push x to stack1 (assuming size of stacks is unlimited).

deQueue(q)
 1) If both stacks are empty then error.
 2) If stack2 is empty
   While stack1 is not empty, push everything from stack1 to stack2.
 3) Pop the element from stack2 and return it.

Метод 2 определенно лучше, чем метод 1. Метод 1 перемещает все элементы дважды в операции enQueue, в то время как метод 2 (в операции deQueue) перемещает элементы один раз и перемещает элементы, только если стек2 пуст.

10
задан 2 July 2009 в 14:41
поделиться

5 ответов

Не совсем уверен, как это сделать в ASP.NET (не пробовал раньше), но в целом, если HTTP-клиент поддерживает HTTP v1.1 (на что указывает версия его request), сервер может отправить заголовок ответа Transfer-Encoding, в котором указано «chunked», а затем отправить данные ответа с использованием нескольких блоков данных по мере их доступности. Это позволяет осуществлять потоковую передачу данных в режиме реального времени, когда вы заранее не знаете окончательный размер данных (и, следовательно, не можете установить заголовок ответа Content-Length). Дополнительные сведения см. В RFC 2616 , раздел 3.6.

2
ответ дан 3 December 2019 в 21:22
поделиться

Try adding the following header.

Response.AddHeader("Content-Length", zipSize);

I know that was causing me issues before.

Edit:

These other 2 may help as well:

Response.AddHeader("Content-Description", "File Transfer");
Response.AddHeader("Content-Transfer-Encoding", "binary");
0
ответ дан 3 December 2019 в 21:22
поделиться

Вы пробовали очистить ZipOutputStream перед сбросом ответа? Можете ли вы сохранить zip-архив на клиенте и протестировать его с помощью zip-утилиты?

0
ответ дан 3 December 2019 в 21:22
поделиться

Боже, это много кода! Ваша работа будет проще, если использовать DotNetZip . Предполагая, что у клиента HTTP 1.1, это работает:

Response.Clear();
Response.BufferOutput = false;
string archiveName= String.Format("archive-{0}.zip", DateTime.Now.ToString("yyyy-MMM-dd-HHmmss"));
Response.ContentType = "application/zip";
// see http://support.microsoft.com/kb/260519
Response.AddHeader("content-disposition", "attachment; filename=" + archiveName);  
using (ZipFile zip = new ZipFile())
{
    // filesToInclude is a IEnumerable<String> (String[] or List<String> etc)
    zip.AddFiles(filesToInclude, "files");
    zip.Save(Response.OutputStream);
}
// Response.End(); // will throw an exception internally.
// Response.Close(); // Results in 'Failed - Network error' in Chrome.
Response.Flush(); // See https://stackoverflow.com/a/736462/481207
// ...more code here...

Если вы хотите зашифровать zip паролем, то перед AddFiles () вставьте следующие строки:

    zip.Password = tbPassword.Text; // optional
    zip.Encryption = EncryptionAlgorithm.WinZipAes256; // optional

Если вам нужен самораспаковывающийся архив, замените zip.Save () с помощью zip.SaveSelfExtractor ().


Дополнение; некоторые люди прокомментировали мне , что DotNetZip «не годится», потому что он создает весь ZIP-файл в памяти перед его потоковой передачей. Это не так. Когда вы звоните AddFiles , библиотека создает список записей - объектов, которые представляют состояние вещей, которые нужно заархивировать. До вызова функции «Сохранить» сжатие или шифрование не выполняется. Если вы укажете поток для вызова Save (), тогда все сжатые байты будут переданы напрямую клиенту.

В модели SharpZipLib можно создать запись, затем передать ее в потоковом режиме, затем создать другую запись и передать ее в потоковом режиме и т. Д. С DotNetZip ваше приложение сначала создает полный список записей, а затем отправляет их все. Ни один из подходов не обязательно «быстрее», чем другой, хотя для длинных списков файлов, скажем 30 000, время до первого байта будет быстрее с SharpZipLib. С другой стороны, я бы не рекомендовал динамически создавать zip-файлы с 30 000 записей.


ИЗМЕНИТЬ

Начиная с DotNetZip v1.9, DotNetZip также поддерживает ZipOutputStream. Я все же думаю, что проще делать то, что я показал здесь.


У некоторых людей есть случай, когда у них есть zip-содержимое, которое «в основном одинаково» для всех пользователей, но есть пара файлов, которые разные для каждого из них. DotNetZip тоже хорош в этом. Вы можете прочитать zip-архив из файла файловой системы, обновить несколько записей (добавить несколько, удалить несколько и т. Д.), А затем сохранить в Response.OutputStream. В этом случае DotNetZip не повторно сжимает или повторно шифрует записи, которые вы не изменили. Намного быстрее.

Конечно, DotNetZip предназначен для любого приложения .NET, а не только для ASP.NET. Так что вы можете сохранить в любой поток.

Если вам нужна дополнительная информация, посетите сайт или разместите сообщение на форуме dotnetzip .

Однако проще делать то, что я показал здесь.


У некоторых людей есть случай, когда у них есть zip-содержимое, которое «в основном одинаково» для всех пользователей, но есть пара файлов, которые разные для каждого из них. DotNetZip тоже хорош в этом. Вы можете прочитать zip-архив из файла файловой системы, обновить несколько записей (добавить несколько, удалить несколько и т. Д.), А затем сохранить в Response.OutputStream. В этом случае DotNetZip не повторно сжимает или повторно шифрует записи, которые вы не изменили. Намного быстрее.

Конечно, DotNetZip предназначен для любого приложения .NET, а не только для ASP.NET. Так что вы можете сохранить в любой поток.

Если вам нужна дополнительная информация, посетите сайт или разместите сообщение на форуме dotnetzip .

Однако проще делать то, что я показал здесь.


У некоторых людей есть случай, когда у них есть zip-содержимое, которое «в основном одинаково» для всех пользователей, но есть пара файлов, которые разные для каждого из них. DotNetZip тоже хорош в этом. Вы можете прочитать zip-архив из файла файловой системы, обновить несколько записей (добавить несколько, удалить несколько и т. Д.), А затем сохранить в Response.OutputStream. В этом случае DotNetZip не повторно сжимает или повторно шифрует записи, которые вы не изменили. Намного быстрее.

Конечно, DotNetZip предназначен для любого приложения .NET, а не только для ASP.NET. Так что вы можете сохранить в любой поток.

Если вам нужна дополнительная информация, посетите сайт или разместите сообщение на форуме dotnetzip .


У некоторых людей есть случай, когда у них есть zip-содержимое, которое «в основном одинаково» для всех пользователей, но есть пара файлов, которые разные для каждого из них. DotNetZip тоже хорош в этом. Вы можете прочитать zip-архив из файла файловой системы, обновить несколько записей (добавить несколько, удалить несколько и т. Д.), А затем сохранить в Response.OutputStream. В этом случае DotNetZip не повторно сжимает или повторно шифрует записи, которые вы не изменили. Намного быстрее.

Конечно, DotNetZip предназначен для любого приложения .NET, а не только для ASP.NET. Так что вы можете сохранить в любой поток.

Если вам нужна дополнительная информация, посетите сайт или разместите сообщение на форуме dotnetzip .


У некоторых людей есть случай, когда у них есть zip-содержимое, которое «в основном одинаково» для всех пользователей, но есть пара файлов, которые разные для каждого из них. DotNetZip тоже хорош в этом. Вы можете прочитать zip-архив из файла файловой системы, обновить несколько записей (добавить несколько, удалить несколько и т. Д.), А затем сохранить в Response.OutputStream. В этом случае DotNetZip не повторно сжимает или повторно шифрует записи, которые вы не изменили. Намного быстрее.

Конечно, DotNetZip предназначен для любого приложения .NET, а не только для ASP.NET. Так что вы можете сохранить в любой поток.

Если вам нужна дополнительная информация, посетите сайт или разместите сообщение на форуме dotnetzip .

Вы можете прочитать zip-архив из файла файловой системы, обновить несколько записей (добавить несколько, удалить несколько и т. Д.), А затем сохранить в Response.OutputStream. В этом случае DotNetZip не повторно сжимает или повторно шифрует записи, которые вы не изменили. Намного быстрее.

Конечно, DotNetZip предназначен для любого приложения .NET, а не только для ASP.NET. Так что вы можете сохранить в любой поток.

Если вам нужна дополнительная информация, посетите сайт или разместите сообщение на форуме dotnetzip .

Вы можете прочитать zip-архив из файла файловой системы, обновить несколько записей (добавить несколько, удалить несколько и т. Д.), А затем сохранить в Response.OutputStream. В этом случае DotNetZip не повторно сжимает или повторно шифрует записи, которые вы не изменили. Намного быстрее.

Конечно, DotNetZip предназначен для любого приложения .NET, а не только для ASP.NET. Так что вы можете сохранить в любой поток.

Если вам нужна дополнительная информация, посетите сайт или разместите сообщение на форуме dotnetzip .

14
ответ дан 3 December 2019 в 21:22
поделиться

For those who would miss the ZipOutputStream of SharpZipLib, here is a simple code that makes it possible to use DotNetZip the "regular .NET stream way".

However, take note that it is inefficient compared to a real on-the-fly streaming solution like SharpZipLib does, as it uses an internal MemoryStream before actually calling the DotNetZip.Save() function. But unfortunately, SharpZibLib does not sports EAS Encryption yet (and certainly never). Let's hope that Cheeso will add this functionality in dotNetZip any time soon ? ;-)

/// <summary>
/// DotNetZip does not support streaming out-of-the-box up to version v1.8.
/// This wrapper class helps doing so but unfortunately it has to use
/// a temporary memory buffer internally which is quite inefficient
/// (for instance, compared with the ZipOutputStream of SharpZibLib which has other drawbacks besides).
/// </summary>
public class DotNetZipOutputStream : Stream
{
    public ZipFile ZipFile { get; private set; }

    private MemoryStream memStream = new MemoryStream();
    private String nextEntry = null;
    private Stream outputStream = null;
    private bool closed = false;

    public DotNetZipOutputStream(Stream baseOutputStream)
    {
        ZipFile = new ZipFile();
        outputStream = baseOutputStream;
    }

    public void PutNextEntry(String fileName)
    {
        memStream = new MemoryStream();
        nextEntry = fileName;
    }

    public override bool CanRead { get { return false; } }
    public override bool CanSeek { get { return false; } }
    public override bool CanWrite { get { return true; } }
    public override long Length { get { return memStream.Length; } }
    public override long Position
    {
        get { return memStream.Position; }
        set { memStream.Position = value; }
    }

    public override void Close()
    {
        if (closed) return;

        memStream.Position = 0;
        ZipFile.AddEntry(nextEntry, Path.GetDirectoryName(nextEntry), memStream);
        ZipFile.Save(outputStream);
        memStream.Close();
        closed = true;
    }

    public override void Flush()
    {
        memStream.Flush();
    }

    public override int Read(byte[] buffer, int offset, int count)
    {
        throw new NotSupportedException("Read");
    }

    public override long Seek(long offset, SeekOrigin origin)
    {
        throw new NotSupportedException("Seek");
    }

    public override void SetLength(long value)
    {
        memStream.SetLength(value);
    }

    public override void Write(byte[] buffer, int offset, int count)
    {
        memStream.Write(buffer, offset, count);
    }
}
1
ответ дан 3 December 2019 в 21:22
поделиться
Другие вопросы по тегам:

Похожие вопросы: