使用ASP.NET MVC 2上传文件的最佳方法是什么?

时间:2011-01-25 04:28:23

标签: asp.net-mvc asp.net-mvc-2 file-upload httpmodule ihttpasynchandler

上传可变大小的文件(非常大或非常小的ASP.NET MVC 2应用程序文件系统)的最佳方法是什么?

这是我目前所理解的:

似乎有两种方式可以让人们处理这个问题。 (我们假设文件可能非常大或非常小)

(1)通过Request.FilesHttpPostedFileBase处理控制器操作中的上传,这似乎有一个缺点,即因为ASP.NET将文件加载到活动内存中需要很长时间。

(2)早期使用HttpModule拦截文件上传,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 个答案:

答案 0 :(得分:2)

如果我从ASP.NET 2.0中正确记得大文件被刷新到磁盘,那么即使使用HttpPostedFileBase也不应该有任何内存/性能问题。我不确定asynccontrollers是否是这里的解决方案,asynccontrollers用于长时间运行的服务器进程。有关AsyncControllers的示例,请参阅http://www.aaronstannard.com/post/2011/01/06/asynchonrous-controllers-ASPNET-mvc.aspx

答案 1 :(得分:0)

我使用此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);
            }
        }
    });
}