如何在ASP.NET中创建fileupload接口

时间:2011-07-21 14:16:22

标签: asp.net file-upload

我正在尝试在ASP.NET webforms中创建一个文件上传界面,我正在寻找有关如何继续进行的一些建议。

文件上传界面是我正在制作的网站的一部分,用户可以在其上发布广告。该界面是“创建新广告”的一部分,并允许用户上传最多6张图片。我只使用asp.net FileUpload服务器控件,因为我正在尝试创建一个控件,当用户禁用javascript时它将起作用。这就是背景。

单击按钮时会发生所有6个文件的上传。这将文件存储在临时文件夹(/ UserUploads / temp)中,直到用户提交表单,在这种情况下,文件被移动到/ UserUploads文件夹和数据库中的引用,或者直到用户点击取消按钮或导航到在哪种情况下删除文件。

第一个问题是:以正确的方式将文件存储在临时目录中吗?或者是否有更好的方法将临时文件保存在服务器上,直到提交父表单为止?我能想到的唯一选择是将文件保存到会话中,但这似乎是杀死服务器的一种方法......

第二个问题:当用户关闭浏览器窗口时,我不清楚该怎么做。我想避免在临时目录中出现乱七八糟的文件。有没有办法确保如果用户没有通过表单提交,所有文件都会被清除?或者我只需要经常清理临时目录吗?

第三个问题:我这样做是否完全错误,实际上有更好的方法来上传多个文件?

3 个答案:

答案 0 :(得分:1)

文件上传总是很烦人。我最近发现了一个很棒的组件,可以完成我所相信的所有上传组件应该做的事情。

见: http://aquantum-demo.appspot.com/file-upload

C#中的示例: https://github.com/BoSchatzberg/jfu-CSharp-Example

并且,您应该在创建数据库行之前将文件存储在临时文件夹中。为了避免乱七八糟的文件无用,你可以使用windows临时文件夹在删除或不删除那些文件时对窗口进行说明。

System.IO.Path.GetTempPath()

答案 1 :(得分:1)

1)如果您使用的是SQL Server,我个人更喜欢将上传的文件存储在varbinary(max)字段中,并使用它们的唯一ID进行处理。然后,您不必担心名称冲突或数据库与文件系统的不同步。这也允许您的上传过程独立于父表单的插入。

以下示例显示如何从FileUpload中的FormView控件中获取文件流(和元数据),并将其作为参数提供给SQL存储过程。然后,实现IHTTPHandler的类用于从数据库中检索文件。

2)就清除临时文件而言,我会将每个上传的文件与临时主记录相关联,以便将它们捆绑在一起。确认真正的主设备后,删除临时主设备(以及来自真实主设备的参考文件)。然后定期运行SQL代理作业以删除超过X时间的临时主服务器和关联文件。

保存:

Protected Sub DetailsView1_ItemInserting(ByVal sender As Object, ByVal e As System.Web.UI.WebControls.DetailsViewInsertEventArgs) Handles DetailsView1.ItemInserting
    Dim objUploader As FileUpload = DetailsView1.FindControl("fuFile")
    If objUploader.HasFile Then
        Dim strFileName As String = objUploader.PostedFile.FileName
        strFileName = strFileName.Substring(strFileName.LastIndexOf("\") + 1)
        Dim objFileStream As System.IO.Stream = objUploader.PostedFile.InputStream
        Dim arrFileImageByteArray(objFileStream.Length) As Byte
        objFileStream.Read(arrFileImageByteArray, 0, objFileStream.Length)
        e.Values.Insert(0, "FileImage", arrFileImageByteArray)
        e.Values.Insert(1, "FileName", strFileName)
        e.Values.Insert(3, "PostingDate", Now)
        e.Values.Insert(5, "Application", "CorpForms")
    Else
        e.Cancel = True
        objMessages.Add(New StatusMessage(MessageType.Warning, "File Upload canceled.  No file was selected."))
    End If
End Sub

检索:

Public Class FileServiceHandler : Implements IHttpHandler

    Public Sub ProcessRequest(ByVal context As HttpContext) Implements IHttpHandler.ProcessRequest

        Dim idFileID As Guid
        If context.Request.QueryString("FileID") IsNot Nothing Then
            Dim strFileID As String = context.Request.QueryString("FileID")
            Try
                idFileID = Guid.Parse(strFileID)
            Catch ex As Exception
                Throw New Exception("Unable to parse File ID")
            End Try
        End If

        Dim objConnection As New SqlConnection(ConfigurationManager.ConnectionStrings("PublicWebConnectionString").ConnectionString)
        Dim objCommand As SqlCommand = objConnection.CreateCommand
        Dim objReader As SqlDataReader

        objCommand.CommandType = Data.CommandType.StoredProcedure
        objCommand.CommandText = "spGetUploadedFile"
        objCommand.Parameters.AddWithValue("FileID", idFileID.ToString)

        Dim arrFileImage() As Byte = Nothing
        Dim strFileName As String = String.Empty
        Try
            objConnection.Open()
            objReader = objCommand.ExecuteReader
            While objReader.Read
                If Not IsDBNull(objReader("FileImage")) Then
                    arrFileImage = objReader("FileImage")
                End If
                If Not IsDBNull(objReader("FileName")) Then
                    strFileName = objReader("FileName")
                End If
            End While
        Catch ex As Exception
            Throw New Exception("There was a problem retreiving the file: " & ex.Message)
        End Try
        If objConnection.State <> Data.ConnectionState.Closed Then
            objConnection.Close()
        End If
        If arrFileImage IsNot Nothing Then
            context.Response.Clear()
            context.Response.AddHeader("content-disposition", "attachment;filename=" & strFileName)
            context.Response.BinaryWrite(arrFileImage)
            context.Response.End()
        Else
            context.Response.ContentType = "text/plain"
            context.Response.Write("Unable to retrieve file ID# " & idFileID.ToString)
        End If
    End Sub

    Public ReadOnly Property IsReusable() As Boolean Implements IHttpHandler.IsReusable
        Get
            Return True
        End Get
    End Property

End Class

文件检索路径中的Web.Config:

<configuration>
  <system.web>
    <httpHandlers>
      <add verb="GET" path="*" type="MyNamespace.FileServiceHandler" />
    </httpHandlers>
  </system.web>
    <system.webServer>
        <handlers>
            <add name="MyNamespace.FileServiceHandler" path="*" verb="*" type="MyNamespace.FileServiceHandler" resourceType="Unspecified" preCondition="integratedMode" />
        </handlers>
    </system.webServer>
</configuration>

答案 2 :(得分:0)

我建议将文件存储在数据库中,而不是临时文件夹中。

不要将它们存储在会话Db中 - 信息太多,但在文件数据库记录中包含SessionId。

所以你有一个带有

行表的文件数据库
 Id (int identity field)
 Data (varbinary(max))
 MimeType (varchar(50))
 SessionId (varchar(50))

 UserId ??

然后,您只需编写一个计划的SQL任务来清除会话已过期的图像。