Создан пользовательский файл загрузки. MD5 Hash не совпадает - PullRequest
2 голосов
/ 12 января 2011

Используя Asp.Net MVC, я создавал загрузчик файлов.Проблема со встроенными функциями Asp.Net MVC заключается в том, что они не работают при очень больших загрузках файлов, а в некоторых браузерах они не открывают диалоговое окно сохранения как.Таким образом, я покатился сам, используя статью из msdn http://support.microsoft.com/kb/812406. Проблема сейчас в том, что файлы загружаются идеально, но контрольные суммы MD5 не совпадают, потому что размер файла на сервере немного отличается от размера загрузки (дажехотя 1000 тестов показывают, что загрузки выполняются просто отлично).Вот код:

public class CustomFileResult : ActionResult
{
    public string File { get; set; }

    public CustomFileResult(string file)
    {
        this.File = file;
    }

    public override void ExecuteResult(ControllerContext context)
    {
        Stream iStream = null;

        // Buffer to read 10K bytes in chunk:
        byte[] buffer = new Byte[10000];

        // Length of the file:
        int length;

        // Total bytes to read:
        long dataToRead;

        // Identify the file name.
        string filename = System.IO.Path.GetFileName(this.File);

        try
        {
            // Open the file.
            iStream = new System.IO.FileStream(this.File, System.IO.FileMode.Open,
                        System.IO.FileAccess.Read, System.IO.FileShare.Read);


            // Total bytes to read:
            dataToRead = iStream.Length;

            context.HttpContext.Response.ContentType = "application/octet-stream";
            context.HttpContext.Response.AddHeader("Content-Disposition", "attachment; filename=" + filename);

            // Read the bytes.
            while (dataToRead > 0)
            {
                // Verify that the client is connected.
                if (context.HttpContext.Response.IsClientConnected)
                {
                    // Read the data in buffer.
                    length = iStream.Read(buffer, 0, 10000);

                    // Write the data to the current output stream.
                    context.HttpContext.Response.OutputStream.Write(buffer, 0, length);

                    // Flush the data to the HTML output.
                    context.HttpContext.Response.Flush();

                    buffer = new Byte[10000];
                    dataToRead = dataToRead - length;
                }
                else
                {
                    //prevent infinite loop if user disconnects
                    dataToRead = -1;
                }
            }
        }
        catch (Exception ex)
        {
            // Trap the error, if any.
            context.HttpContext.Response.Write("Error : " + ex.Message);
        }
        finally
        {
            if (iStream != null)
            {
                //Close the file.
                iStream.Close();
            }
            context.HttpContext.Response.Close();
        }
    }
}

И исполнение:

return new CustomFileResult(file.FullName);

Ответы [ 4 ]

2 голосов
/ 12 января 2011

Попробуйте использовать метод

Response.TransmitFile(string fileName) 

.

Это действительно хорошо, и есть некоторые вещи, которых следует избегать, кроме OutOfMemory.

1 голос
/ 12 января 2011

Оказывается, что проблема в отсутствующем заголовке.

context.HttpContext.Response.AddHeader("Content-Length", iStream.Length.ToString());

Добавление этого заголовка решило проблему.

0 голосов
/ 12 января 2011

Начав запись в OutputStream, попробуйте очистить сам OutputStream, а не очищать ответ: context.HttpContext.Response.OutputStream.Flush()

0 голосов
/ 12 января 2011

Ваша проблема здесь:

length = iStream.Read(buffer, 0, 10000);

// Write the data to the current output stream.
context.HttpContext.Response.OutputStream.Write(buffer, 0, length);

Каждый цикл, который вы читаете в буфер ровно 10000 байт и записывает его в поток.Это означает, что каждый загружаемый файл будет кратен 10000.Таким образом, если бы я должен был загрузить файл размером 9 998 байт с вашего сайта, полученный файл был бы 10 000 байт.Это означает, что хеш никогда не совпадет.Мой файл будет иметь 2 нулевых байта в конце.

Вам нужно добавить проверку, чтобы убедиться, что объем данных для чтения>> 10 Кб, а если нет, измените размер своего байта доточное количество, которое осталось, и передать это.это должно исправить несоответствие хеша

попробуйте что-то вроде этого:

if (context.HttpContext.Response.IsClientConnected)
{
 // Read the data in buffer.
 if (dataToRead>=10000)
 {
   byte[] buffer = new byte[10000];
   length = 10000
   context.HttpContext.Response.OutputStream.Write(buffer, 0, length);
 }
 else
 {
   byte[] buffer = new byte[dataToRead];
   length = buffer.Length;
   context.HttpContext.Response.OutputStream.Write(buffer, 0, length);  
 }
 // Flush the data to the HTML output.
 context.HttpContext.Response.Flush();

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