Лучший способ справиться с большим сайтом загрузки? - PullRequest
2 голосов
/ 13 января 2009

В настоящее время у меня есть сайт загрузки для моей школы, основанный на .net. Мы предлагаем для загрузки все, что угодно, от антивируса, AutoCAD, SPSS, Office и ряда крупных приложений. В настоящее время настроено обрабатывать их одним из двух способов; все, что более 800 мегабайт, напрямую доступно через отдельный веб-сайт, а менее 800 мегабайт защищено за кодом .net с использованием файлового потока для передачи его пользователю в виде фрагментов по 10 000 байт. У меня возникают всевозможные проблемы с подачей загрузок таким образом ... Я хотел бы иметь возможность защитить большие загрузки, но сайт .net просто не может их обработать, а файлы меньшего размера часто выходят из строя. Есть ли лучший подход к этому?

edit - я просто хотел узнать, как я наконец решил эту проблему: в итоге я добавил свой каталог загрузки в качестве виртуального каталога в iis и указал собственный обработчик http. Обработчик извлек имя файла из запроса и проверил наличие разрешений на основании этого, затем либо перенаправил пользователей на страницу ошибки / входа в систему, либо разрешил продолжить загрузку. У меня не было проблем с этим решением, и я работаю над ним уже 7 месяцев, обслуживая файлы размером несколько гигов.

Ответы [ 7 ]

5 голосов
/ 13 января 2009

Если у вас проблемы с производительностью и вы доставляете файлы, которые существуют в файловой системе (по сравнению с БД), используйте функцию HttpResponse.TransmitFile .

Что касается сбоев, у вас, вероятно, есть ошибка. Если вы отправите код, вам может быть лучше ответ.

2 голосов
/ 13 января 2009

Загляни в бит торрент. Он разработан специально для такого рода вещей и довольно гибкий.

1 голос
/ 13 января 2009

У меня есть две рекомендации:

  • Увеличьте размер буфера, чтобы меньше итераций

И / ИЛИ

  • Не вызывайте IsClientConnected на каждой итерации.

Причина в том, что в соответствии с Руководством Microsoft :

Response.IsClientConnected имеет некоторые затраты, поэтому используйте его только перед операцией, которая занимает, по крайней мере, 500 миллисекунд (это длительное время, если вы пытаетесь поддерживать пропускную способность в десятки страниц в секунду). Как общее правило, не вызывайте его на каждой итерации узкого цикла

0 голосов
/ 13 января 2009

Amazon S3 звучит идеально для того, что вам нужно, но это коммерческий сервис, а файлы подаются со своих серверов.

Вы должны попытаться связаться с Amazon и запросить академическую цену. Даже если у них его нет.

0 голосов
/ 13 января 2009

Существует множество лицензионных ограничений ... например, у нас есть лицензионное соглашение Office 2007, в котором говорится, что любой технический персонал в кампусе может загружать и устанавливать Office, но не студенты. Поэтому мы не позволяем студентам скачать его. Поэтому мы решили скрыть эти загрузки за .net.

0 голосов
/ 13 января 2009

Хорошо, вот как это выглядит сейчас ...

    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;

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

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

        context.Response.Clear();
        context.Response.Buffer = false;
        context.Response.ContentType = "application/octet-stream";
        Int64 fileLength = iStream.Length;
        context.Response.AddHeader("Content-Length", fileLength.ToString());
        context.Response.AddHeader("Content-Disposition", "attachment; filename=" + originalFilename);

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

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

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

                buffer = new Byte[10000];
                dataToRead = dataToRead - length;
            }
            else
            {
                //prevent infinite loop if user disconnects
                dataToRead = -1;
            }
        }
        iStream.Close();
        iStream.Dispose();
    }
    catch (Exception ex)
    {
        if (iStream != null)
        {
            iStream.Close();
            iStream.Dispose();
        }
        if (ex.Message.Contains("The remote host closed the connection"))
        {
            context.Server.ClearError();
            context.Trace.Warn("GetFile", "The remote host closed the connection");
        }
        else
        {
            context.Trace.Warn("IHttpHandler", "DownloadFile: - Error occurred");
            context.Trace.Warn("IHttpHandler", "DownloadFile: - Exception", ex);
        }
        context.Response.Redirect("default.aspx");
    }
}
0 голосов
/ 13 января 2009

Что не так с использованием надежного веб-сервера (такого как Apache) и позволяет ему работать с файлами. Так же, как вы теперь разделяете большие файлы на веб-сервере, почему бы не обслуживать меньшие файлы так же?

Есть ли какие-то скрытые требования, чтобы предотвратить это?

...