Каков наилучший способ загрузки файлов с ASP.NET MVC 2?

Каков наилучший способ загрузки файлов переменного размера (очень большого или очень маленького размера в файловую систему приложения 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 ответа

Решение

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

Я использую этот инструмент JavaScript

Это контроллер (я дважды проверяю, потому что 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);
            }
        }
    });
}
Другие вопросы по тегам