在ASP時候,寫個上傳檔案都很麻煩,因為ASP本身沒有支援上傳的物件,必須使用第三方物件來進行上傳功能的實作,到了ASP.NET上傳實在很簡單,拉個FileUpload物件,寫簡單的幾行程式,馬上可以有上傳功能。
有了上傳,那下載呢?
下載就很笨,通常是網頁帶「Link」的方式,例如:「http://localhost/files/KKBruce.zip」這樣的方式來讓人下載。好一點的架個FTP,但還是寫個管理Link資料庫及程式,例如:「http://localhost/files/download.asp?id=1」取出「ftp://localhost/files/bruce/blog.zip」來讓使用者下載。久而久之,檔案一多還是不好管理,又要管檔案,又要管理Link!
所以想就使用「資料庫」來管理,這裡指的資料庫不是那種管理「路徑」的Table,而且將檔案整個存到Table裡,需要時再取出來使用,以下我們就來實作上傳檔案至資料庫,由資料庫取出檔案下載兩部份。
01 | ****** Object: Table [dbo].[Files] Script Date : 08/26/2010 17:12:17 ******/ |
05 | SET QUOTED_IDENTIFIER ON |
11 | CREATE TABLE [dbo].[Files]( |
12 | [uid] [ int ] IDENTITY(1,1) NOT NULL , |
13 | [ Name ] [nvarchar](50) NOT NULL , |
14 | [Body] [varbinary]( max ) NOT NULL , |
15 | [ Size ] [ decimal ](18, 0) NOT NULL , |
16 | [SaveDateTime] [datetime] NOT NULL , |
17 | [LastUseDateTime] [datetime] NULL |
我們先建一個資料表,裡面最重要的是「Body」,Body就是要儲存檔案的地方,而一般網路資料或書籍資料都是使用「
Image資料類型」,但查看MSDN後發現,如果你是使用SQL Server 2005以後的版本,
請改使用請改用 nvarchar(max)、varchar(max) 和 varbinary(max)。
在未來的 Microsoft SQL Server 版本中,將移除 ntext、text 和 image 等資料類型。請避免在新的開發工作中使用這些資料類型,並規劃修改目前在使用這些資料類型的應用程式。請改用 nvarchar(max)、varchar(max) 和 varbinary(max)。
以上是要注意的地方。
接下來我們來實作上傳檔案到資料庫,然後再從資料庫下載檔案。
新增Default.aspx在UI部份:
02 | < asp:FileUpload ID = "FU" runat = "server" /> |
04 | < asp:Button ID = "SaveFile" runat = "server" Text = "上傳" /> |
09 | 編號:< asp:TextBox ID = "TextBox1" runat = "server" ></ asp:TextBox > |
10 | < asp:Button ID = "DownFile" runat = "server" Text = "下載" /> |
我們針對SaveFile及DownFile來撰寫程式碼:
SaveFile事件:
01 | Protected Sub SaveFile_Click( ByVal sender As Object , ByVal e As System.EventArgs) Handles SaveFile.Click |
03 | If Not FU.HasFile Then |
04 | Response.Write( "沒有上傳的檔案!" ) |
11 | Dim buf( Me .FU.PostedFile.ContentLength - 1) As Byte |
12 | Me .FU.PostedFile.InputStream.Read(buf, 0, Me .FU.PostedFile.ContentLength) |
14 | Dim conn As New SqlConnection(WebConfigurationManager.ConnectionStrings( "SCS" ).ConnectionString) |
17 | Dim cmd As New SqlCommand( "INSERT INTO Files(Name,Body,Size,SaveDateTime) VALUES (@filename,@body,@size, @sdt);" , conn) |
18 | cmd.Parameters.AddWithValue( "@filename" , FU.PostedFile.FileName) |
20 | cmd.Parameters.AddWithValue( "@body" , buf) |
21 | cmd.Parameters.AddWithValue( "@size" , FU.PostedFile.ContentLength.ToString) |
22 | cmd.Parameters.AddWithValue( "@sdt" , Now) |
27 | rs = cmd.ExecuteNonQuery |
28 | Response.Write( "新增成功" ) |
DownFile事件:
01 | Protected Sub DownFile_Click( ByVal sender As Object , ByVal e As System.EventArgs) Handles DownFile.Click |
05 | If String .IsNullOrEmpty( Me .TextBox1.Text) Then |
06 | Response.Write( "請輸入下載ID編號" ) |
12 | Dim conn As New SqlConnection(WebConfigurationManager.ConnectionStrings( "SCS" ).ConnectionString) |
13 | Dim cmd As New SqlCommand( "Select * from Files Where uid = @id" , conn) |
14 | cmd.Parameters.AddWithValue( "@id" , id) |
16 | Dim dr As SqlDataReader |
20 | dr = cmd.ExecuteReader |
23 | Response.ClearHeaders() |
26 | Response.Buffer = True |
29 | Dim Name As String = dr.GetString(1) |
31 | Response.AddHeader( "Accept-Language" , "zh-tw" ) |
33 | Response.AddHeader( "content-disposition" , "attachment; filename=" & Chr(34) & Name & Chr(34)) |
34 | Response.ContentType = "Application/octet-stream" |
36 | Response.BinaryWrite(dr( "Body" )) |
其實不難:
- 將檔案轉為Byte,然後存進資料庫的二進位欄位;
- 取出資料,進行二進位輸出。
不管是Excel、Word、MP3、Text、ZIP…反正只要是檔案都可以上傳及下載。以上還有很多可以改進的地方,例如統計的部份,或使用其他方式(Session…)來取得下載檔案。
參考:
你好:我是你電子報的訂閱戶,我有VB程式的問題想問你可乎?
回覆刪除1).Txt 檔如果要取得最後一筆資料的 Record number,除一筆一筆直出到最後外,有無更便捷的法方?
2).陣列如果要傳值至副程式去運用,除了設定 Public 外有無方法?
謝謝!!
Dear Vincent
回覆刪除我很樂意幫忙,盡我所能。
1. 非文章主題,可以Mail到「kingkong點bruce(at)gmail點com」來討論。
2. 如果方便,請將原始程式碼壓縮再mail給我。
3. 你的問題二,我看不太懂?再說清楚一些。
請問一下
回覆刪除程式第42行不需要Response.End(),可是為何第44行卻又執行一次呢?
謝謝.
你好,請問這種上傳下載方式在Office2007相關檔案是否需做什麼調整呢?目前遇到下載excel2007檔案會出現下面訊息:
回覆刪除Excel在“12.xlsx”中发现不可读取内容。是否恢复工作簿的内容?如果信任此工作簿的来源,请单击“是”。
单击“是”后:Excel 已完成文件级验证和修复。此工作簿的某些部分可能已被修复或丢弃。
(Word2007也是同樣錯誤訊息)
謝謝
禎禎,我的建議是
回覆刪除1. 資料庫部份,新增一個 MIME 欄位,然後在上傳檔案時,將檔案正確的MIME一併寫入。
2. 在下載檔案時(DownFile事件 34行),指定正確的 MIME。
其實,最好的辦法是「上傳前的檔案都要經過壓縮」,那一定沒問題。
MIME 與 檔案的對應,你自己上網查一下「MIME」即有很多資料。
回覆刪除請問有C#的版本嗎??因為很需要~~希望前輩不吝指教!!感謝
回覆刪除請問有C#的版本嗎??因為很需要~~希望前輩不吝指教!!感謝
回覆刪除http://www.developerfusion.com/tools/convert/csharp-to-vb/
回覆刪除C#我幫不了你,你可以試著使用線上工具,看能不能動。
不好意思 想請問 我是將圖片存入資料庫
回覆刪除資料庫是用sql
我資料表欄位是用varbinary(MAX)
我要怎麼讀取二進制的值與在前台顯示
http://blog.kkbruce.net/p/mvc.html#mvc3upload
回覆刪除我個人是不建議使用 Database 來儲存圖片。
假設以下這種情況:
你想想,如果你的table裡有 10000 筆人事資料好了,每筆有個大頭照,大頭照 5KB 就好,
在使用類類似 Gridview 時,又沒事先處理好分頁,
5 * 10000 = 50000 KB,光圖片資料就要傳多久?
而且資料庫爆量成長也是一個問題。
當然,每個系統都有自己的理由,
http://msdn.microsoft.com/zh-tw/magazine/cc163933(en-us).aspx
這裡有教,
另外,我附上的 mvc 文章有些討論的 Link 最好也看一下。