アップロードファイルmultiad form-data boundary説明


意味ENCTYPE=「multiipad/form-data」説明:
httpプロトコルでファイルをアップロードするrfc 1867プロトコルの概要、jspアプリケーションの例、クライアントはコンテンツ構造を送信する.
1、概説は最初のhttpプロトコルにおいて、ファイルをアップロードする機能がない.rfc 1867(http://www.ietf.org/rfc/rfc1867.txt)httpプロトコルにこの機能を追加しました.クライアントのブラウザは、Microsoft IE、Mozla、Operaなどのように、ユーザーが指定したファイルをサーバに送信します.サーバー側のウェブページプログラムは、php、asp、jspなどのように、ユーザーが送ってきたファイルをこの仕様で解析することができます.Microsoft IE,Mozia,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>

ユーザーは複数のファイルを選択し、フォームの他の項目を記入し、「提出」ボタンをクリックしてからアップロードを開始します.http://192.168.29.65/upload_file/UploadFile
これはserveletプログラムの注意enctype=「multiiPad/form-data」で、method=post、type=「file」です.rfc 1867によれば、この3つの属性は必須である.multiiprt/form-dataは、バイナリファイルの伝送効率を向上させるために追加された符号化タイプです.具体的な説明はrfc 18672を参照してください.サービス端末serveletの作成は現在第三者のhttp uload fileツールライブラリが多いです.Jarkataプロジェクト自体がfileupladパッケージを提供しています.http://jakarta.apache.org/commons/fileupload/.
ファイルのアップロード、フォーム項目の処理、効率の問題はほぼすべて考慮しました.Strutsではこのカバンを使っていますが、Strutsで別に包装しました.ここで直接fileupladカバンを使います.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)abXccクライアントは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 abbXXXccc
-----------------------------7d33a816d302b6

Content-Disposition: form-data; 

name="text1" foo

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

Content-Disposition: form-data;

name="password1" bar

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

(上には回車があります.)この内容は最後の回車を含めて、一文字に欠けていません.
注意:Contint-Length:424ここの424は、最終的な返車を含む赤色コンテンツの全体長である.
この行に注意してください.コンテント-Type:multiiPad/form-data;boundary=----------7 d 33 a 816 d 302 b 6
rfc 1867によると、multiipad/form-dataは必須です.------------------7 d 33 a 816 d 302 b 6はセパレータで、複数のファイル、フォーム項目を分離します.
33 a 816 d 302 b 6は、ファイルまたはフォーム項目の内容に全体の区切りが表示されないことを確認するために、即時に生成された数字である.前の--------7 dはIE特有のマークです.
Moziaは-------------71はこの例を手作業で送り、上記のservletで検査に合格した.
POSTを使ってデータを送る
POST方式でデータを送信するのは、主にサーバにより多くのクライアントのデータを送信するためであり、URLの長さに制限されない.POST要求は、データをURLで符号化した形式でHTTP本文に置く.フィールド形式はfieldname=valueであり、各フィールドを&分離する.注意すべてのフィールドは文字列として処理されます.実は私たちがやるべきのは、ブラウザPOSTを模擬するフォームです.以下はIEが登録フォームのPOST要求を送信するものである.POST http://127.0.0.1/login.do HTTP/1.0
Accept: image/gif, image/jpeg, image/pjpeg, */*
Accept-Language: en-us,zh-cn;q=0.5
Content-Type: application/x-www-form-urlencoded
User-Agent: Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1)
Content-Length: 28
/r/n
username=admin&password=1234
MIDPアプリケーションでこのPOST要求をアナログブラウザで送信するには、まずHttpConnectionを設定する要求方式がPOSTです.hc.setRequestMethod(HttpConnection.POST);次にHTTP本文を作成します.byte[] data = "username=admin&password=1234".getBytes();

   , Content-Type Content-Length:

hc.setRequestProperty("Content-Type", "application/x-www-form-urlencoded");
hc.setRequestProperty("Content-Length", String.valueOf(data.length));

   OutputStream :

OutputStream output = hc.openOutputStream();
output.write(data);
注意したいのは、データは依然としてURLで符号化される必要があります.MIDPライブラリにはJ 2 SEに対応するURLEncoder類がないので、自分でこのencode()を作成する必要があります.java.net.URLEncoder.javaのソースを参照することができます.残りはサーバーの応答を読み取ることです.コードはGETと一致します.ここでは詳しく説明しません.
multiad/form-dataを使ってファイルを送ります.
MIDPクライアントでサーバーにファイルをアップロードするには、POST multip/form-dataタイプのリクエストをシミュレーションしなければなりません.Contint-Typeはmultip/form-dataでなければなりません.
multipart/form-dataで符号化されたPOST要求フォーマットはaplication/x-wn-urlencodedとは全く違っています.multiad/form-dataはまずHTTP要求ヘッダにセパレータを設定する必要があります.例えばABCD:hc.setRequestProperty("Content-Type", "multipart/form-data; boundary=ABCD");はその後、各フィールドを「--セパレータ」で区切り、最後の「--セパレータ-」で終了を表します.例えば、titleフィールド「Today」とファイルC:/1.txtをアップロードするには、HTTP本文は以下の通りです.--ABCD
Content-Disposition: form-data; name="title"
/r/n
Today
--ABCD
Content-Disposition: form-data; name="1.txt"; filename="C:/1.txt"
Content-Type: text/plain
/r/n
< 1.txt >
--ABCD--
/r/n
各行は最後の行を含めて/r/nで終了しなければなりません.SnifferプログラムでIEが送信したPOST要求を検出すると、IEのセパレータは--------------7 d 4 a 6 d 588 c 9に類似していることが判明し、これはIEが生成した乱数であり、アップロードファイルにセパレータが発生することを防ぐため、サーバがファイルの開始位置を正しく識別できなくなる.固定のセパレータを書いてもいいです.複雑であれば十分です.
送信ファイルのPOSTコードは以下の通りです.String[] props = ... // 
String[] values = ... // 
byte[] file = ... // 
String BOUNDARY = "---------------------------7d4a6d158c9"; // 
StringBuffer sb = new StringBuffer();
//  :
for(int i=0; i
sb = sb.append("--");
sb = sb.append(BOUNDARY);
sb = sb.append("/r/n");
sb = sb.append("Content-Disposition: form-data; name=/""+ props[i] + "/"/r/n/r/n");
sb = sb.append(URLEncoder.encode(values[i]));
sb = sb.append("/r/n");
}
//  :
sb = sb.append("--");
sb = sb.append(BOUNDARY);
sb = sb.append("/r/n");
sb = sb.append("Content-Disposition: form-data; name=/"1/"; filename=/"1.txt/"/r/n");
sb = sb.append("Content-Type: application/octet-stream/r/n/r/n");
byte[] data = sb.toString().getBytes();
byte[] end_data = ("/r/n--" + BOUNDARY + "--/r/n").getBytes();
//  HTTP :
hc.setRequestProperty("Content-Type", MULTIPART_FORM_DATA + "; boundary=" + BOUNDARY);
hc.setRequestProperty("Content-Length", String.valueOf(data.length + file.length + end_data.length));
//  :
output = hc.openOutputStream();
output.write(data);
output.write(file);
output.write(end_data);
//  :
// TODO...