close

預先提醒 : 不管是FileUpload還是檔案下載功能 都不能放在UpdatePanel中
也就是不能使用AJAX來處理

因為工作上的需求 要做一個檔案下載的功能
在網路上找了與多資料 測試的結果最終都沒能成功的把檔案下載的功能完備
後來又努力的找了一番資料終於完成了

我想環境可能是個因素導致許多範例最後都沒有成功
先說明一下功能的需求

檔案上傳的功能之前已經完成了
使用FileUpload元件進行檔案上傳也沒有啥好講的 頂多就是上傳前多一些檢查
這也不過是一些IF或者其他的迴圈判斷而已

唯一要說明的是
檔案上傳再設計之時就已經將路徑資訊寫入資料庫
由於要求的設計比較簡單 所以其實存放路徑只有一個目錄 下面在分目錄而已 也就是根目錄下只有一層目錄

例如
根目錄是網路上某台FileServer分享出來的目錄
//fileServer/share/

而上傳前會去檢查這個路徑下是不是有已經開好要上傳的目錄

例如
我之前設計的需求是要依照文件的編號來分
因為會去檢查根目錄下是不是已經存在該目錄

有的話 就直接上傳 沒有就建立
這部分是標準的VB.net語法
要注意的只有必須 Imports System.IO

'檢查是否有檔案

        'MyFiles為FileUpload物件
        If MyFiles.HasFile Then 

' 建立目錄物件類別
' FilePath則是我依照上面說的檔案的存放根目錄+文件編號組成的目錄路徑
            Dim dir As New DirectoryInfo(FilePath)

' 檢查目錄是否存在 不存在就建立目錄
            If Not dir.Exists Then
                dir.Create()
            End If

' 進行檔案上傳
            Try

               ' 把檔案利用FileUpload物件的SaveAs方法進行上傳 
               ' 要給予完整的存檔路徑加上檔名 其中一般檔案資料夾結構需要注意的事項要在組出路徑時就處理好 
               ' 例如 不能有特殊字元 根目錄/子目錄/檔案 之間的 "/"要注意別遺漏了

                MyFiles.SaveAs(FilePath & MyFiles.FileName)
                Return True

            Catch ex As Exception

                ' 上傳失敗時回傳一個布林值 尤其他程序處理
 
                ' 因為我的Function是設計回傳布林值的參數 當然也可以設計成回傳其他東西
                Return False
            End Try
 
        End If

以上就是上傳檔案我所處理的方式.
當然另外有個函式會在上傳成功後接著把檔案的路徑.檔名...等相關資訊放到DataBase
這樣下載時才有依據
接下來讓我們來看檔案下載的部分

------------------------------------------------------ ---------------------------------------------------------------------

網路上只要搜尋ASP.Net 檔案下載 應該就可以找到一堆資料
有的還很詳細告訴你哪一行程式是做啥 可是我就是組不出我要的功能
其實我要的功能 也不算複雜 就是檔案下載而已咩

所以我也不確定 我的寫法是不是正確 有需要的網友 如果測試有問題 也不要贛矯我....
或許環境是個很重要的因素吧

我的開發環境是VS2008 .net 3.5 + IIS 6 使用VB.net
測試環境則是IE 6 跟 IE7 重要的是 我的瀏覽器 再瀏覽我設計的功能時 是使用 Unicode UTF-8 編碼

因為用Big-5編碼 根本就無法瀏覽我的網頁
至於網頁編碼問題.....我不懂 也不在這篇記述的範圍 有興趣深入的網友就自行找解答吧
小弟只是把開開發經驗Port上來~@@(好像不是很負責)

接下來就是我的Code 一樣是寫一個Function處理

'判斷檔案是否存在 
        ' fileName是已經從資了庫取出路徑 檔名 組合好的完整檔案所在路徑
        ' 例如 //fileserver/Share/DocNumber/test.pd
        If fileName IsNot Nothing And System.IO.File.Exists(fileName) Then
 
            ' 從緩衝區資料流清除所有標頭 
            Response.ClearHeaders()

            ' 從緩衝區清除所有內容輸出 
            Response.Clear()

            ' 快取分鐘數 0 表示快取立刻過期 
            Response.Expires = 0

            ' 使用緩衝輸出 在資料流完整處理後輸出 
            Response.Buffer = True

            ' 加入HTTP標頭.應該是設定語言吧.... 
           Response.AddHeader("Accept-Language", "zh-tw")

            ' 加入HTTP標頭 設定所取得的文件內容是一個附加檔而不是內嵌資料 這樣就不會用瀏覽器去開啟 
            Response.ContentType = "application/save-as"            

            '  加入HTTP標頭設定 
            '  content-disposition 是 增加一個MIME部署 
            '  attachment 表示內容是一個附加檔 
            '  fileName就是上面說的檔案完整路徑 比較特別的是 路徑要經過 HttpUtility.UrlEncode 來對Url的路徑進行編碼處理 
            '  不然 在小弟環境中的測試 是會發生一些其奇怪怪的狀況 
            '  例如 檔案下載了 卻發生損毀 或者 找到檔案 要下載卻沒有檔名 檔名 是該網頁的名稱 類別不明 
            Response.AddHeader("content-disposition", "attachment ; filename=" & HttpUtility.UrlEncode(fileName))

            '  開始輸出 有的範例是使用 Response.Write() 我的測試 一樣會有怪狀況
            Response.WriteFile(fileName) 

            '  結束輸出 有的範例沒有...不過 我個人認為還是養成好習慣 東西開完 不用了就要關
            Response.End()
 
        Else 
            Response.Write("找不到檔案") 
        End If

以上 今天的報告內容~
可以在我的環境中完整下載"任何檔案" 包括中文檔名 不過中文路徑沒有試過~~~
也有些文章會建議把檔案路徑設定成虛擬目錄.然後直接給超連結就可以下載檔案了
這是最快也最沒問題的方法

而為何我要設計成目前的方式呢?
因為通常企業中都會有自己的檔案伺服器防放檔案 實在沒理由把檔案儲存這種東西放在Web Server上
另外給超連結的方式或暴露檔案的所在位置 有點功夫的user可能就會透過Url連結去找到該檔案目錄

除非你的檔案目錄還設定了權限 可是這樣在我的設計目標下是不可行的
因為不知道放文件是什麼人 他會開啥資料夾
當然嚴格說 還是可以從他的帳號取得資訊 去對應他在企業中的帳號 然後開資料夾時設定權限

不過衍生的問題是 這樣下來要寫的Code好像也不少
小弟下一個專案就是要架構一個Web的檔案管理系統
到時候恐怕少不了這一段

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 ADOLPH 的頭像
    ADOLPH

    ADOLPH 手抄印帳

    ADOLPH 發表在 痞客邦 留言(1) 人氣()