傳統 `FileSystemObject` 僅支援文字檔讀寫,無法處理二進位上傳。早期解法多依賴第三方元件(需註冊、有版權標示、相容性差)。本文從 HTTP 協定層面剖析上傳機制,並給出純 ASP 實作核心代碼。
| 機制 | 核心特性 | 適用性 |
|---|---|---|
| RFC1867 (multipart/form-data) | 表單新增 ``,採用 MIME 多部分編碼,效率高、不編碼二進位資料,瀏覽器原生支援「瀏覽」按鈕 | ✅ Web 應用首選,彈性最高,ASP/ASP.NET/PHP/Java 皆支援 |
| HTTP PUT | HTTP 1.1 新增 PUT 動詞,直接寫入伺服器資源,繞過應用層,需 ISAPI Filter 攔截處理 | ❌ 破壞可程式性,極少用於 Web 應用 |
| WebDAV | 擴充 HTTP 動詞支援鎖定/版控/上傳,Office「存到 Web」即基於此 | ⚠️ 適合內容發布,不適合應用層整合上傳邏輯 |
結論:RFC1867 是 Web 應用整合檔案上傳的最佳標準。
<!-- upload.htm -->
<form action="upload.asp" method="post" enctype="multipart/form-data">
<input type="file" name="upfile">
<input type="submit" value="上傳">
</form>
<!-- upload.asp 核心片段 -->
<%
Dim FormData, FormSize, DataStart, CLStr, DivStr
FormSize = Request.TotalBytes
FormData = Request.BinaryRead(FormSize) ' 讀取原始二進位資料
CLStr = ChrB(13) & ChrB(10) ' CRLF
' 找到雙重 CRLF 結束的 header 結尾,資料起始位置
DataStart = InStrB(FormData, CLStr & CLStr) + 4
' 取得分隔境界字串 (第一行)
DivStr = LeftB(FormData, InStrB(FormData, CLStr) - 1)
' 計算檔案資料長度(扣除尾部境界)
DataSize = InStrB(DataStart + 1, FormData, DivStr) - DataStart - 2
' 擷取純檔案二進位內容
FormData = MidB(FormData, DataStart, DataSize)
' 使用 ADO Stream 儲存
Dim objStream
Set objStream = Server.CreateObject("ADODB.Stream")
objStream.Type = 1 ' adTypeBinary
objStream.Open
objStream.Write FormData
objStream.SaveToFile Server.MapPath("uploads/") & "filename.ext", 2 ' adSaveCreateOverWrite
objStream.Close
Set objStream = Nothing
%>
Request.BinaryRead:唯一能讀取 `multipart/form-data` 原始二進位資料的方法。ChrB(13)&ChrB(10):二進位環境下的 CRLF,字串函數需用 `InStrB`/`MidB`/`LeftB` 等 B 系列。ADODB.Stream:支援二進位讀寫、大檔案分段處理、編碼轉換,是純 ASP 處理二進位檔案的核心物件。RFC1867 定義的 `multipart/form-data` 至今仍是 HTTP 檔案上傳的通用標準(HTML5 `FormData` API 底層即此)。理解其封包結構與解析邏輯,不僅能維護舊 ASP 系統,更能深入理解現代前後端檔案上傳協定,排查疑難雜症(如 Boundary 衝突、大檔案斷點續傳、雲端儲存簽名直傳等)。