Каков наилучший способ загрузки файлов с ASP.NET MVC 2? - PullRequest
6 голосов
/ 25 января 2011

Каков наилучший способ загрузки файлов переменного размера (очень большого или очень маленького размера в файловую систему приложения ASP.NET MVC 2)?

Это то, что я понимаю до сих пор:

Кажется, что есть два способа, которыми люди справляются с этим.(Предположим, что файлы могут быть очень большими или очень маленькими)

(1) Обработать загрузку в действии контроллера с помощью Request.Files или HttpPostedFileBase, что, по-видимому, имеет недостаток, заключающийся в длительном использовании, посколькуASP.NET загружает файлы в активную память.

или

(2) перехватывает загрузку файла на раннем этапе с помощью модуля HttpModule, который каким-то образом обходит проблему производительности.(Я немного пасмурно из-за того, как это работает, но я использовал этот пост http://darrenjohnstone.net/2008/07/15/aspnet-file-upload-module-version-2-beta-1/ в качестве ссылки). Часть, о которой я размышляю, заключается в том, в какой момент ASP.NET загружает отправленные файлы в активную память, и как перехват этого в модуле фактически изменяет это поведение.

Со второго вариантабыстрее, кажется, лучший вариант.Но похоже, что приложение, отправляющее форму загрузки, вероятно, будет иметь некоторые данные, связанные с файлом, которые необходимо сохранить в базе данных.Я не хочу делать постоянные вызовы в моем HttpHandler или HttpModule (потому что тогда у меня будут две очень похожие функциональности, встречающиеся в разных местах: контроллер и обработчик http).

Я думаю, что одним из обходных путей было бы сохранение местоположения целевого файла в HttpContext.Items, но это лучший способ?

Последнее беспокойство по поводу этогоЯ хочу визуализировать HttpResponse до окончания загрузки файла.Поэтому, если файл большой, я отправлю пользователю представление со значением статуса загрузки и сделаю вызовы AJAX, чтобы сохранить статус обновленным. Как отобразить результат, сохраняя процесс загрузки?Нужно ли делать AsyncHandler или AsyncController?Нужно ли вручную захватывать другую ветку?

Большое спасибо, ребята.Я знаю, что это много вопросов, и, вероятно, отражает общее отсутствие понимания о чем-то.Забавная вещь в общем отсутствии понимания состоит в том, что люди, у которых они есть, также имеют тенденцию испытывать недостаток в понимании того, чего им не хватает ... так что, если кто-то может указать мне правильное направление на этой ноте, я был бы признателен,

Ответы [ 2 ]

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

Если я правильно помню, из ASP.NET 2.0 большие файлы сбрасываются на диск, поэтому даже при использовании HttpPostedFileBase не должно быть никаких проблем с памятью / производительностью. Я не уверен, что asynccontrollers - это решение здесь, asynccontrollers для длительных процессов сервера. Пример отключения AsyncControllers см. http://www.aaronstannard.com/post/2011/01/06/asynchonrous-controllers-ASPNET-mvc.aspx

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

Я использую этот javascript tool

Это контроллер (я проверяю дважды, потому что IE ведет себя странно):

<HttpPost()> _
Function UploadExcelPriceList(ByVal id As String) As System.String

    Dim bResult As Boolean = False
    Dim IsIE As Boolean = False
    Dim sFileName As String = ""

    If (Request.Files Is Nothing) OrElse (Request.Files.Count = 0) Then
        If String.IsNullOrEmpty(Request.Params("qqfile")) Then
            Return ("{success:false, error:'request file is empty'}")
        Else
            sFileName = Request.Params("qqfile").ToString
        End If
    Else
        sFileName = Request.Files(0).FileName
        IsIE = True
    End If

    If String.IsNullOrEmpty(sFileName) Then
        Return ("{success:false, error:'request file is empty'}")
    End If

    Dim DocumentName As String = Id & Path.GetExtension(sFileName)

    If IsIE Then
        Try
            Request.Files(0).SaveAs(Path.Combine(My.Settings.TempFolder, DocumentName))
        Catch ex As Exception
            Return ("{success:false, error:'" & ex.Message & "'}")
        End Try
    Else
        Try
            If (Request.InputStream IsNot Nothing) AndAlso (Request.InputStream.CanRead) AndAlso (Request.InputStream.Length > 0) Then
                Using fileStream As FileStream = New FileStream(Path.Combine(My.Settings.TempFolder, DocumentName), FileMode.Create)
                    Dim FileBytes(Core.Convert.ToInt32(Request.InputStream.Length)) As Byte
                    Dim bytesRead As Int32 = 0
                    bytesRead = Request.InputStream.Read(FileBytes, 0, FileBytes.Length)
                    fileStream.Write(FileBytes, 0, bytesRead)
                    fileStream.Flush()
                    fileStream.Close()
                    bytesRead = Nothing
                End Using
            End If
        Catch ex As Exception
            Return ("{success:false, error:'" & ex.Message & "'}")
        End Try
    End If

    Return ("{success:true, id: '" & Id & "'}")

End Function

Я вставил этот HTML вмой взгляд:

<div id="PopupExcelUploader" title="Carica Listino Excel">
    <div id="uploaderFile"></div>
</div>

и это JavaScript:

function CreateFileUploader() {
    var uploader = new qq.FileUploader({
        element: $('#uploaderFile')[0],
        template: '<div class="qq-uploader">' +
                              '<div class="qq-upload-drop-area"><span>Drop files here to upload</span></div>' +
                              '<div class="qq-upload-button ui-button ui-widget ui-corner-all ui-button-text-only ui-state-default">Seleziona il Listino Excel</div>' +
                              '<ul class="qq-upload-list"></ul>' +
                              '</div>',
        hoverClass: 'ui-state-hover',
        focusClass: 'ui-state-focus',
        action: UploaderAction,
        allowedExtensions: ['xls', 'xlsx'],
        params: { id: ModelId },
        onSubmit: function(file, ext) {
        },
        onComplete: function(id, fileName, responseJSON) {
            if ((responseJSON.success == null) || (responseJSON.success == 'false')) {
                $.jGrowl("Error!", { theme: 'MessageError', life: 3000 });
            }
            else {
                documentUploaded = true;
                $.jGrowl("Document uploaded successfully!", { theme: 'MessageOk', life: 1800 });
                window.setTimeout(function() {
                    $("#PopupExcelUploader").dialog('close');
                    $("#PriceListDynamicGrid").trigger("reloadGrid");
                }, 3000);
            }
        }
    });
}
...