1. 程式人生 > >使用http 上傳檔案的原理

使用http 上傳檔案的原理

可參考的文章有:

http://www.cnblogs.com/kaixuan/archive/2008/01/31/1060284.html

) 為 http 協議添加了這個功能。客戶端的瀏覽器,如 Microsoft IE, Mozila, Opera 等,按照此規範將使用者指定的檔案傳送到伺服器。伺服器端的網頁程式,如 php, asp, jsp 等,可以按照此規範,解析出使用者傳送來的檔案。
Microsoft IE, Mozila, Opera 已經支援此協議,在網頁中使用一個特殊的 form 就可以傳送檔案。
絕大部分 http server ,包括 tomcat ,已經支援此協議,可接受傳送來的檔案。
各種網頁程式,如 php, asp, jsp 中,對於上傳檔案已經做了很好的封裝。

2、上傳檔案的例項:用 servelet 實現(http server 為 tomcat 4.1.24)
1. 在一個 html 網頁中,寫一個如下的form :

<form enctype="multipart/form-data"  action="http://192.168.29.65/UploadFile" method=post >

load multi files :<br>

<input name="userfile1" type="file" ><br>

<input name="userfile2" type="file"><br>

<input name="userfile3" type="file"><br>

<input name="userfile4" type="file"><br>

text field :<input type="text" name="text" value="text"><br>

<input type="submit" value=" 提交 "><input type=reset>

</form>

2. 服務端 servelet 的編寫
現在第三方的 http upload file 工具庫很多。Jarkata 專案本身就提供了fileupload 包

http://jakarta.apache.org/commons/fileupload/  。檔案上傳、表單項處理、效率問題基本上都考慮到了。在 struts 中就使用了這個包,不過是用 struts 的方式另行封裝了一次。這裡我們直接使用 fileupload 包。至於struts 中的用法,請參閱 struts 相關文件。
這個處理檔案上傳的 servelet 主要程式碼如下:

public void doPost( HttpServletRequest request, HttpServletResponse response ) {

DiskFileUpload diskFileUpload = new DiskFileUpload();

//  允許檔案最大長度

diskFileUpload.setSizeMax( 100*1024*1024 );

//  設定記憶體緩衝大小

diskFileUpload.setSizeThreshold( 4096 );

//  設定臨時目錄

diskFileUpload.setRepositoryPath( "c:/tmp" );

List fileItems = diskFileUpload.parseRequest( request );

Iterator iter = fileItems.iterator();

for( ; iter.hasNext(); ) {

FileItem fileItem = (FileItem) iter.next();

if( fileItem.isFormField() ) {

//  當前是一個表單項

out.println( "form field : " + fileItem.getFieldName() + ", " + fileItem.getString() );

} else {

//  當前是一個上傳的檔案

String fileName = fileItem.getName();

fileItem.write( new File("c:/uploads/"+fileName) );

}

}

}

為簡略起見,異常處理,檔案重新命名等細節沒有寫出。

3、 客戶端傳送內容構造

假設接受檔案的網頁程式位於 http://192.168.29.65/upload_file/UploadFile .
假設我們要傳送一個二進位制檔案、一個文字框表單項、一個密碼框表單項。檔名為 E:/s ,其內容如下:(其中的XXX代表二進位制資料,如 01 02 03)

a

bb

XXX

ccc

客戶端應該向  192.168.29.65  傳送如下內容:

POST /upload_file/UploadFile HTTP/1.1

Accept: text/plain, */*

Accept-Language: zh-cn

Host: 192.168.29.65:80

Content-Type:multipart/form-data;boundary=---------------------------7d33a816d302b6

User-Agent: Mozilla/4.0 (compatible; OpenOffice.org)

Content-Length: 424

Connection: Keep-Alive

-----------------------------7d33a816d302b6

Content-Disposition: form-data; name="userfile1"; filename="E:/s"

Content-Type: application/octet-stream

a

bb

XXX

ccc

-----------------------------7d33a816d302b6

Content-Disposition: form-data; name="text1"

foo

-----------------------------7d33a816d302b6

Content-Disposition: form-data; name="password1"

bar

-----------------------------7d33a816d302b6--

此內容必須一字不差,包括最後的回車。
注意:Content-Length: 424 這裡的424是紅色內容的總長度(包括最後的回車)
注意這一行:
Content-Type: multipart/form-data; boundary=---------------------------7d33a816d302b6
根據 rfc1867, multipart/form-data是必須的.
---------------------------7d33a816d302b6 是分隔符,分隔多個檔案、表單項。其中 33a816d302b6 是即時生成的一個數字,用以確保整個分隔符不會在檔案或表單項的內容中出現。前面 的 ---------------------------7d 是 IE 特有的標誌。 Mozila 為 ---------------------------71
用手工傳送這個例子,在上述的 servlet 中檢驗通過。

(上面有一個回車) 使用者可以選擇多個檔案,填寫表單其它項,點選“提交”按鈕後就開始上傳給  http://192.168.29.65/upload_file/UploadFile  這是一個 servelet 程式
注意 enctype="multipart/form-data", method=post, type="file" 。根 據 rfc1867, 這三個屬性是必須的。multipart/form-data 是新增的編碼型別,以提高二進位制檔案的傳輸效率。具體的解釋請參 閱 rfc1867.

第二篇文章使用perl實現的:

http://www.vivtek.com/rfc1867.html

RFC1867 HTTP file upload

RFC1867 is the standard definition of that "Browse..." button that you use to upload files to a Web server. It introduced the INPUT field type="file", which is that button, and also specified a multipart form encoding which is capable of encapsulating files for upload along with all the other fields on an upload form.

It's not easy to find documentation on how to work with this stuff, though. Partly this is because if you're writing a Perl CGI it's really rather easy to work with, and partly it's due to the fact that Microsoft IIS ASP doesn't (exactly) support RFC1867 file upload. So on the one hand the Unixheads think it's too trivial to document, while the ASP script kiddies think that file upload is the exclusive preserve of genius and guru alike. I.e. Bill doesn't think you need to use it.

If that last sounds overly bitter, it's because I just finished up a really horrible job that involved uploading files to an IIS server. It would have been nice had somebody at Microsoft found file upload a sufficiently significant function to design competently. As it is, IIS 5.0 now provides a "Request.ReadBinary" method that gives you the whole request in plaintext, and graciously allows you to design your own object to read it. Note that VBS has no (easy) ability to read this binary data.

So let's assume for the time being that you're working with some reasonable non-IIS server. How do you really deal with file upload? It turns out to be easy. First, you design your form so that it will actually do an upload. In short, do this:

<form action=/mycode.cgi method=post enctype=multipart/form-data

>

<input type="file"
>

</form>

In case you were wondering, the standard encoding type for a form is application/x-www-form-urlencoded, and if you leave the multipart enctype out of your form, then Netscape, for one, will not upload the file, it'll just include the filename. If that's what you actually want, this is pretty useful. (However, the RFC leaves behavior in this situation undefined, so you shouldn't rely on any particular behavior. I haven't looked to see what IE does in this situation. Undoubtedly something different.)

So this much information I already knew going into my horrible project, or at least knew of it. That's why I assumed that the server end was just as simple. And as I mentioned, in Perl it isn't much more difficult than retrieving normal posted data is already. It's just that IIS doesn't support multipart/form-data posts, that's all. Oh, Microsoft has a solution of sorts, called the something-or-other manager, and IIS 5.0 is so powerful that this manager thingy is now included right in the service pack with, gee, at least a kilobyte of documentation.

Yeesh. I'm off-track again, aren't I?

OK, so when this post gets to the server, what does it look like? Well, first of all the Content-type header of the request is set to
  multipart/form-data; boundary=[some stuff]
This is how you can ascertain that you're really dealing with a properly encoded upload post. The boundary value is probably of the form --------------------------------1878979834, where the digits are randomly generated. This boundary is a MIME boundary; it's guaranteed not to appear anywhere in the data except between the multiple parts of the data.

The data itself appears in blocks that are made up of lines separated by CR/LF pairs. It looks like this, more or less:

-------------------------------18788734234

Content-Disposition: form-data; name="nonfile_field"



value here

-------------------------------18788734234

Content-Disposition: form-data; name="myfile"; filename="ad.gif"

Content-Type: image/gif



[ooh -- file contents!]

-------------------------------18788734234--

As you can see, this post isn't from the form I listed above, because I threw in a non-upload field just to show what it looks like. Anyway, you can see where everything is. Note that you get the originating local filename of the document for free in this format, meaning that you can use this to develop a document management system. Actual implementation is left as an exercise for the reader. I'll write more later on this topic, especially if you ask me any questions. Hint, hint.

So a Perl reader for this guy is simple: you iterate on the lines of the input and break on your boundary. Do things with the parts as you find them. I have an extensive example that you can read and use, which you can see here. It works (I'm using it daily) and it's well-documented.

And thus concludes the lesson for today. Go forth and upload files.

LINKS

  • An interesting RFC, actually, as it goes into some of the alternatives that the working group rejected in the interest of a clean design.

具體協議請看:

http://tools.ietf.org/html/rfc1867

http://tools.ietf.org/html/rfc2854

http://tools.ietf.org/html/rfc2388

相關推薦

使用http 檔案原理

可參考的文章有: http://www.cnblogs.com/kaixuan/archive/2008/01/31/1060284.html ) 為 http 協議添加了這個功能。客戶端的瀏覽器,如 Microsoft IE, Mozila, Opera 等,按照此規範

spring框架檔案原理探究

    <bean id="multipartResolver"           class="org.springframework.web.multipart.commons.CommonsMultipartRe

HTTP檔案至伺服器

本人最近開發MFC專案需要利用HTTP協議,上傳檔案至伺服器,需要以二進位制傳輸,Content-Type型別為: multipart/form-data,注意需要定義相關邊界開始和結束 利用WinInt開發包HTTP封裝  //HTTP服務  CHttpConnecti

http檔案和進度監控以及構造multipart/form-data請求

http上傳檔案 html程式碼 <!DOCTYPE html> <html> <head> <meta charset="utf-8">

django 20、檔案原理解析

最近還是被django的上傳大檔案搞得暈頭轉向,轉而看了這方面的原理,把自己的心得寫了出來。 首先,我想說:如果你使用的是django預設的FileField的形式通過表單上傳,那麼其實你完全不需要管理如何上傳,或者自己去寫一個分塊讀取寫入的函式, 這個是django已經

Qt Http QHttpMultiPart檔案到java http伺服器

                         Qt Http QHttpMultiPart上傳檔案到java http伺服器 1.最近專案用到了Qt上傳檔案到HT

golang http clietn 檔案

今天使用網上無意間看到了搜狗圖片上傳,使用瀏覽器的方式實現的。於是就用go嘗試了下 //上傳檔案的api uploadUrl := "http://" file, err := os.OpenFile("QQ20180817-202205.png", os.O_RDONLY, os

C# 實現http get post async sync 檔案

程式碼: using System; using System.Collections.Generic; using System.IO; using System.Linq; using System.Net; using System.Text; using System.Threading

java後臺發起檔案的post請求(http和https)

分享一下我的偶像大神的人工智慧教程!http://blog.csdn.net/jiangjunshow 也歡迎轉載我的文章,轉載請註明出處 https://blog.csdn.net/aabbyyz 一、http post 對於檔案上傳,客戶端通常就是頁

java後臺發起檔案的post請求 http和https

一、http post 對於檔案上傳,客戶端通常就是頁面,在頁面裡實現上傳檔案不是什麼難事,寫個form,加上enctype = "multipart/form-data",在寫個接收的就可以了,沒什麼難的。如: <!DOCTYPE 

PHP使用CURL向Python,Golang傳送檔案表單檔案[HTTP協議下Api]

PHP傳送方程式碼段: <?php /** * htppCurl表單上傳檔案 * @param $file FILE_ADDR * @param string $url uri * @param string $key key * @return bool|mixed *

php 檔案時Internal Server Error或者mod_fcgid: HTTP request length 136136 (so far) exceeds MaxRequestLen

php檔案上傳時遇到這個坑:Internal Server Error,查了Apache下的日誌資訊,才知道: mod_fcgid: HTTP request length 136136 (so fa

winform檔案,利用http,form-data格式

/// <summary> /// 上傳檔案 /// </summary> /// <param name="url">服務地址</param> /// <param name="filePath">檔案路徑</param> public

使用C#利用Http協議從遠端向SharePoint文件庫檔案

在程式中如何向SharePoint文件庫上傳檔案是最普通的程式設計任務,實起來,有2種方式: 一、這項功能實現起來最方便的就是利用伺服器OM,在程式中直接引用SharePoint.dll,裡面有很多關於SharePoint的物件,程式可能直接通過物件的屬性和方法來控制伺服器內SharePoint

HTTP 錯誤 404.13 - Not Found 請求篩選模組被配置為拒絕超過請求內容長度的請求。(檔案長度問題)

HTTP 錯誤 404.13 - Not Found 請求篩選模組被配置為拒絕超過請求內容長度的請求。 問題:HTTP 錯誤 404.13 - Not Found 請求篩選模組被配置為拒絕超過請求內容長度的請求。 原因:Web 伺服器上的請求篩選被配置為拒絕該請求,因為內容長度超過配置的值(

Java程式碼中如何通過 http檔案

例子程式碼如下 package example.filetransfer; import java.io.*; import java.net.*; import java.util.*; public class HttpRequestUtil { /** * 傳送ge

通過 HTTP POST 檔案到伺服器

2. 上傳之前使用者無法預知上傳檔案的數目. 3. 因為是 ASP.NET 應用, 客戶端可能沒有裝 .NET Framework. 其實,我們知道.如果要跟 IE 端客戶檔案系統互動的話,程式碼必須在客戶端執行. 這個時候我們可以寫一個 Activex 控制元件來實現選擇資料夾和上傳. 一般我們常用兩種方

c# http協議檔案+傳輸數資料

using System; using System.Collections.Generic; using System.Collections.Specialized; using System.IO; using System.Linq; using System.Ne

【Android基礎知識】使用Http和HttpClient檔案

public class UploadThread extends Thread{ private String fileName; private String url; public UploadThread(String fileName,String url){ this.fileName

檔案操作】Http的request檔案獲取檔名稱

public static String getFileName(InputStream is) throws IOException { StringBuffer sb =