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

6
什么是上传可变大小的文件(无论是非常大还是非常小)到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吗?我需要手动获取另一个线程吗?
谢谢大家。我知道这是很多问题,并且可能反映了对某些事物的一般理解不足。关于一般缺乏理解的有趣事情是,有这种缺乏理解的人也往往缺乏他们缺乏什么样的理解...因此,如果任何人在这方面指引我方向,我将不胜感激。

可能是[文件上传MVC]的重复问题(https://dev59.com/VEfRa4cB1Zd3GeqP7kR2)。 - jgauffin
@jguaffin - 你链接的问题与此问题毫无关系。 - Fenton
有时候。然而,客户端实现不是这个问题的重点。 - smartcaveman
2个回答

2

你是说关于AsyncController和AJAX的一般规则吗?为什么会这样呢? - smartcaveman
我修改了我的答案,关于Ajax和AsyncControllers的那一行是错误的。 - Wim
在客户端使用http://www.uploadify.com/,在服务器端使用简单的HttpPostedFileBase不是解决您问题的方案吗? - Wim
Uploadify使客户端便利,但为应用程序添加了Flash依赖项。此外,我的问题不是关于客户端集成的,而是关于在ASP.NET接收请求后如何最好地处理请求。正如我在问题中所述,使用HttpPostedFileBase是完成上传文件任务的众多方法之一。我的问题是在文件大小可变时完成任务的最可靠和性能优化的方法是什么。 - smartcaveman
您可以在此处找到有关将文件刷新到磁盘的文档:http://msdn.microsoft.com/zh-cn/library/system.web.httppostedfile.aspx - Wim
显示剩余3条评论

0

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

感谢您提供的代码示例,但是这并没有解决问题。 - smartcaveman

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接