Androidネットワークプログラミング—パラメータとファイルをサーバーにアップロードします。


卒业して二年になりました。仕事も二年になりましたが、具体的な仕事内容のために、本当に上司の要求によってプログラムを书くのは初めてです。
今回は一つの問題に遭遇しました。これまで接触したことがないAndroidネットワークのプログラミングは、指定された3つの方法に従ってPOST方法でHTTPとSocketを使ってサーバーにファイルをアップロードする必要があります。
指定された3つの方法は以下の通りです。
第一種類:形は“のようです。”http://host:port/xxx/xxx/xxx/param?param1=xxx¶m2=xxxの形式
パーティー:
      param 1
      param 2
Data:
      file:アップロードするファイル
第二種類:形は”のようです。http://host:port/xxx/xxx/xxx」の形式
Part 1:
      param 1
Part 2:
      param 2
Part 3:
      file:アップロードするファイル
第三種類:形は”のようです。http://host:port/xxx/xxx/xxx」の形式
Part 1:
      param 1
Part 2:
      param 2
Part 3:
      file:アップロードするファイル
ソケット方法を利用して送ります。
3つの方法は、まず頭がくらくらして、一日中葛藤しました。その後、ようやくいくつかの方法が整理されました。今はこれらの方法を陳列しています。
一つ目と二つ目はHTTPプロトコルをシミュレートして送るもので、HttpURLConnection類を使って送るもので、三つ目はソケット方式を使って送るものです。
まず、アップロードツールの種類を定義しました。UploadUtil.javaでは、Staticのサーバーアドレスを定義しただけです。HOST
コードは以下の通りです
public class UploadUtil {
    
    static String INTERNAL_HOST = "http://host:port/xxx/xxx/xxx/upload/";
    
}
このホストは第一の方法のアドレスの中で、「パラム?」の前にある部分です。
第一の方法を完成する:
第一の方法の「http://host:port/xxx/xxx/xxx/param?param1=xxx¶m2=xxx」実はPOSTのパラメータ、param 1とparam 2を与えていますが、私は便利にするために、直接にパラメータキーの値を書きました。実際には方法の内部でも、入ってきたパラメータを通して、ループをしてみてもいいです。http://host:port/xxx/xxx/xxx/param?param1=xxx¶m2=xxx」の文字列でいいです。最後にURLからurlオブジェクトを生成すればいいです。
public static void queryParam(String fileName)
    {
        String BOUNDARY = "---------------------------7db1c523809b2";//     
        File file = new File(fileName);   //       
        String host = INTERNAL_HOST + "param?param1=xxx¶m2=xxx"; //                     
        
        
        try 
        {
            byte[] after = ("--" + BOUNDARY + "--\r
").getBytes("UTF-8"); // URL Connection URL url = new URL(host); HttpURLConnection conn = (HttpURLConnection)url.openConnection(); // HTTP conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); conn.setRequestProperty("Content-Length", String.valueOf(file.length())); conn.setRequestProperty("HOST", url.getHost()); conn.setDoOutput(true); // Connection OutputStream , OutputStream out = conn.getOutputStream(); InputStream in = new FileInputStream(file); // 。 , 。 byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) != -1) { out.write(buf, 0, len); } // , HTTP 。 //out.write(after); in.close(); out.close(); Log.d("carter", "queryParam : " + conn.getResponseCode()); Log.d("carter", "queryParam : " + conn.getResponseMessage()); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
大体の手順:
1.まずURLサーバアドレスを作成してください。
2.URLオブジェクトを初期化し、中のHttpURLConnectionオブジェクトを得る
3.connectionオブジェクトのヘッダ情報を設定することは、POST方法、HOST、Conteet-Type、Conteet-Lengthなどの属性を含む。
4.アップロードするファイルの内容を書き込む
第二の方法を完成する:
第二の方法は、第一の方法のように簡単にはしたくないですが、基本的な文法構成は似ています。すべてHTTPプロトコルを模倣した形ですから。
第二の方法は、サーバーアドレスにアップロードされたHOSTとPATHのみを提供しています。具体的なパラメータは提供されていませんので、HTTPレポートに追加することで実現します。
public static void multiPart(String fileName)
    {
        String BOUNDARY = "---------------------------7db1c523809b2";//     
        File file = new File(fileName);   //       
        
        //   param         ,       ,    param1 param2
        StringBuilder sb = new StringBuilder();
        sb.append("--" + BOUNDARY + "\r
"); sb.append("Content-Disposition: form-data; name=\"param1\"" + "\r
"); sb.append("\r
"); sb.append("xxx" + "\r
"); sb.append("--" + BOUNDARY + "\r
"); sb.append("Content-Disposition: form-data; name=\"param2\"" + "\r
"); sb.append("\r
"); sb.append("xxx" + "\r
"); // , , 。 sb.append("--" + BOUNDARY + "\r
"); sb.append("Content-Disposition: form-data; name=\"data\"; filename=\"" + fileName + "\"" + "\r
"); sb.append("Content-Type: text/plain" + "\r
"); sb.append("\r
"); try { byte[] before = sb.toString().getBytes("UTF-8"); byte[] after = ("--" + BOUNDARY + "--\r
").getBytes("UTF-8"); URL url = new URL(INTERNAL_HOST); // HttpURLConnection , HttpURLConnection conn = (HttpURLConnection) url.openConnection(); conn.setRequestMethod("POST"); conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); conn.setRequestProperty("Content-Length", String.valueOf(before.length + file.length() + after.length)); conn.setRequestProperty("HOST", url.getHost()); conn.setDoOutput(true); OutputStream out = conn.getOutputStream(); InputStream in = new FileInputStream(file); // out.write(before); // byte[] buf = new byte[1024]; int len; while ((len = in.read(buf)) != -1) { out.write(buf, 0, len); } // , HTTP out.write(after); // out.flush(); // in.close(); out.close(); Log.d("carter", "multipart : " + conn.getResponseCode()); Log.d("carter", "multipart : " + conn.getResponseMessage()); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
具体的な手順は:
1.パラム1等のパラメータをそれぞれフォーマットで組織する
2.HttpURLConnectionオブジェクトを入手し、いくつかの基本的なヘッド属性を設定し、その中のContint-Lengthはすべてのparamとファイルにテールマークを加えた全長である。
3.outputStreamを送信します。
第三の方法を完成する:
第三の方法は第二の方法とよく似ています。ただ、Socketオブジェクトだけを使って、HttpURLConnection方法ではありません。
		public static void socket(String fileName)
    {
        String BOUNDARY = "---------------------------7db1c523809b2";//     
        File file = new File(fileName);   //       
        
        //          
        StringBuilder textParam = new StringBuilder();
        textParam.append("--" + BOUNDARY + "\r
"); textParam.append("Content-Disposition: form-data; name=\"param1\"" + "\r
"); textParam.append("\r
"); textParam.append("xxx" + "\r
"); textParam.append("--" + BOUNDARY + "\r
"); textParam.append("Content-Disposition: form-data; name=\"param2\"" + "\r
"); textParam.append("\r
"); textParam.append("xxx" + "\r
"); // int fileDataLen = 0; // StringBuilder fileParam = new StringBuilder(); fileParam.append("--" + BOUNDARY + "\r
"); fileParam.append("Content-Disposition: form-data;name=\"data\";" + "filename=\"" + fileName + "\"" + "\r
"); fileParam.append("Content-Type: text/plain" + "\r
\r
"); fileParam.append("\r
"); // fileDataLen += fileParam.length(); // fileDataLen += file.length(); // HTTP int totalDataLen = 0; try { byte[] textEntity = textParam.toString().getBytes(); byte[] after = ("--" + BOUNDARY + "--\r
").getBytes(); // , + + totalDataLen = textEntity.length + fileDataLen + after.length; // Socket URL url = new URL(INTERNAL_HOST); Socket socket = new Socket(url.getHost(), 80); socket.setSoTimeout(60000); // Socket // , OutputStream out = socket.getOutputStream(); // String requestMethod = "POST " + url.getPath() + " HTTP/1.1\r
"; out.write(requestMethod.getBytes()); // String accept = "Accept: image/gif, image/jpeg, image/pjpeg, application/x-shockwave-flash, application/xaml+xml," + "application/vnd.ms-xpsdocument, application/x-ms-xbap, application/x-ms-application, application/vnd.ms-excel, " + "application/vnd.ms-powerpoint, application/msword, */*\r
"; out.write(accept.getBytes()); // String language = "Accept-Language: zh-CN\r
"; out.write(language.getBytes()); // String contentType = "Content-Type: multipart/form-data; boundary=" + BOUNDARY + "\r
"; out.write(contentType.getBytes()); // String contentLength = "Content-Length: " + totalDataLen + "\r
"; out.write(contentLength.getBytes()); // String alive = "Connection: Keep-Alive\r
"; out.write(alive.getBytes()); // String host = "Host: " + url.getHost() + ":80\r
"; out.write(host.getBytes()); // out.write("\r
".getBytes()); // out.write(textEntity); // StringBuilder fileEntity = new StringBuilder(); fileEntity.append("--" + BOUNDARY + "\r
"); fileEntity.append("Content-Disposition: form-data;name=\"data\";" + "filename=\"" + fileName + "\"" + "\r
"); fileEntity.append("Content-Type: text/plain" + "\r
\r
"); out.write(fileEntity.toString().getBytes()); // FileInputStream fis = new FileInputStream(file); // null byte[] buffer = new byte[1024]; int len = 0; while( (len=fis.read(buffer))!=-1 ) { out.write(buffer, 0, len); } fis.close(); out.write("\r
".getBytes()); // , out.write(after); // BufferedReader reader = new BufferedReader(new InputStreamReader(socket.getInputStream())); String line = ""; while( (line=reader.readLine())!=null) { Log.d("carter", line); } // out.flush(); // out.close(); reader.close(); socket.close(); } catch (MalformedURLException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (UnsupportedEncodingException e) { // TODO Auto-generated catch block e.printStackTrace(); } catch (IOException e) { // TODO Auto-generated catch block e.printStackTrace(); } }
具体的な手順:
1.パラメータ情報の作成
2.ファイル情報を作成する
3.末尾情報の作成
4.URLとポートでソケットのオブジェクトを得る
5.ソケットのプロパティを設定する
6.出力ストリームを得て、すべての情報を出力する
7.転送結果を出力する
これで三つの方法が実現し、もつれた内容を積極的に実現する必要がある。
以上の方法は、いくつかのパラメータ情報を置き換えるだけで、完全に直接多重化できる。