2012年9月26日 星期三

檔案上傳asp.net

檔案上傳一直是教書以來想要完成的事,可是大部分的書都叫讀者上傳到伺服器的某個資料夾儲存,這會是一個嚴重的問題。這學期教資料庫剛好複習一下,這次使用Visaul Studio 2010,是 ASP.NET 4.0,應該可以用個幾年吧。

1. 首先在設計模式布置FileUpload(負責選取檔案), textbox(負責輸入檔案描述,可空白),Button(負責驅動上傳), Literal(負責上傳後顯示資訊),而Label物件可以不用放。
而對應要儲存檔案的資料表設計如下, fcontent負責儲存檔案內容,ftype負責檔案類型,fsize檔案大小,fname檔案全名(包括附檔名),fext負責附檔名,fdesc是檔案的描述說明, fuploadtiem存上傳的日期時間。
而程式碼uploadfile.aspx.vb的內容如下

Imports System.Data.SqlClient
Imports System.Web.Configuration
Imports System.IO
Partial Class Default4
    Inherits System.Web.UI.Page
    Protected Sub Button1_Click(sender As Object, e As System.EventArgs) Handles Button1.Click
        Dim icnt As Integer = 0, jcnt As Integer = 0
        Dim sqlstring As String = "", merr As String = ""
        Dim fname As String = "", fext As String = "", ftype As String = "", fsize As Integer = 0, fdesc As String = "", fuploadtime As DateTime = DateTime.Now
        '處理上傳檔案、說明及檔案內容存入資料庫
        Using sql_conn As New SqlConnection(WebConfigurationManager.ConnectionStrings("APPSYSConnectionString").ConnectionString)
            sql_conn.Open()
            Using sql_command As New SqlCommand()
                '儲存檔案
                'For icnt = 1 To Request.Files.Count
                Dim fu_file As FileUpload = DirectCast(Page.FindControl("fu_file"), FileUpload)
                Dim tb_file As TextBox = DirectCast(Page.FindControl("tb_file"), TextBox)
                If fu_file.HasFile Then
                    jcnt = jcnt + 1
                    fname = fu_file.FileName
                    fext = Path.GetExtension(fname).ToString()
                    fsize = fu_file.PostedFile.ContentLength
                    Response.Write(fsize)
                    If fsize > 1024000 Then
                        merr = "檔案超過1MB"
                    End If
                    ftype = fu_file.PostedFile.ContentType
                    fdesc = tb_file.Text.Trim()
                    '檔案存入資料庫
                    sqlstring = "insert into 學生證照2 " & "(fname, fext, ftype, fsize, fdesc, fcontent, fuploadtime)"
                    sqlstring &= " values (@fname, @fext, @ftype, @fsize, @fdesc, @fcontent, @fuploadtime)"
                    sql_command.Parameters.Clear()
                    sql_command.CommandText = sqlstring
                    sql_command.Connection = sql_conn
                    sql_command.Parameters.AddWithValue("fname", fname)
                    sql_command.Parameters.AddWithValue("fext", fext.ToLower())
                    sql_command.Parameters.AddWithValue("ftype", ftype)
                    sql_command.Parameters.AddWithValue("fsize", fsize)
                    sql_command.Parameters.AddWithValue("fdesc", fdesc)
                    'fuploadtime是以client的系統時間為準
                    sql_command.Parameters.AddWithValue("fuploadtime", fuploadtime)
                    sql_command.Parameters.AddWithValue("fcontent", fu_file.FileBytes)
                    If merr = "" Then
                        sql_command.ExecuteNonQuery()
                    End If
                Else
                    merr = "沒有選擇任何上傳的檔案!"
                End If

                ' Next

            End Using

        End Using
        'msg_close()呼叫寫在aspx的javascript副程式,javascript必須寫在<head>與</head>中間
        '為了減少複雜性,我將msg_close()的指令去掉了
        If merr <> "" Then
            '顯示錯誤訊息
            lt_show.Text = "<script language=javascript>alert(""" & merr & """);</script>"
        Else
            '完成上傳,返回瀏覽頁
            lt_show.Text = "<script language=javascript>alert(""資料上傳完成!\n"");location.replace(""filedelete_download.aspx"");</script>"
            'lt_show.Text &= "location.replace(""Default5.aspx"");</script>"
        End If

    End Sub
End Class





另外要一提的是預設上傳檔案有大小限制,經過測試約在4MB左右,
因此在web.config <system.web>與 </system.web>之間,加上此行程式(改變上限為10MB) <httpRuntime maxRequestLength="10240"/>
如果超過10MB,瀏覽器的畫面會出現無法顯示網頁

為了避免此畫面,所以網頁可以允許上傳<1MB的檔案,但因為原本uploadfile.aspx.vb中,有小於1MB的條件
  If  fsize > 1024000 Then
                        merr = "檔案超過1MB"
  End If



除了檔案大小外,也可透過限制使用者上傳檔案的附檔名來避免發生太大的檔案,可以google查到使用java script來限制,將原本uploadfile.aspx的html修改,從原本
<asp:FileUpload ID="fu_file" runat="server" /> 改成
 <asp:FileUpload ID="fu_file" runat="server" onchange="return checkFileExtension(this);"/>
此外,將下列指令放在 uploadfile.aspx 原始檔<head>與</head>中,


    <script type="text/javascript">
        function checkFileExtension(elem) {
            var filePath = elem.value;
            if (filePath.indexOf('.') == -1) {
                remove(elem);
                alert('不正確的副檔名格式');
                return false;
            }
            var validExtensions = new Array();
            var ext = filePath.substring(filePath.lastIndexOf('.') + 1).toLowerCase();
            //限制只能選取那些副檔名
            validExtensions[0] = 'jpg';
            validExtensions[1] = 'pdf';
            validExtensions[2] = 'doc';
            validExtensions[3] = 'docx';
            validExtensions[4] = 'jpeg';
            for (var i = 0; i < validExtensions.length; i++) {
                if (ext == validExtensions[i])
                    return true;
            }
            remove(elem);
            alert('不正確的副檔名格式: ' + ext.toUpperCase());
            return false;
        }
        function remove(control) {
            var who = control;
            who.value = "";
            var who2 = who.cloneNode(false);
            who2.onchange = who.onchange;
            who.parentNode.replaceChild(who2, who);
        }
</script>

沒有留言:

張貼留言