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
コードは以下の通りです
第一の方法を完成する:
第一の方法の「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オブジェクトを生成すればいいです。
1.まずURLサーバアドレスを作成してください。
2.URLオブジェクトを初期化し、中のHttpURLConnectionオブジェクトを得る
3.connectionオブジェクトのヘッダ情報を設定することは、POST方法、HOST、Conteet-Type、Conteet-Lengthなどの属性を含む。
4.アップロードするファイルの内容を書き込む
第二の方法を完成する:
第二の方法は、第一の方法のように簡単にはしたくないですが、基本的な文法構成は似ています。すべてHTTPプロトコルを模倣した形ですから。
第二の方法は、サーバーアドレスにアップロードされたHOSTとPATHのみを提供しています。具体的なパラメータは提供されていませんので、HTTPレポートに追加することで実現します。
1.パラム1等のパラメータをそれぞれフォーマットで組織する
2.HttpURLConnectionオブジェクトを入手し、いくつかの基本的なヘッド属性を設定し、その中のContint-Lengthはすべてのparamとファイルにテールマークを加えた全長である。
3.outputStreamを送信します。
第三の方法を完成する:
第三の方法は第二の方法とよく似ています。ただ、Socketオブジェクトだけを使って、HttpURLConnection方法ではありません。
1.パラメータ情報の作成
2.ファイル情報を作成する
3.末尾情報の作成
4.URLとポートでソケットのオブジェクトを得る
5.ソケットのプロパティを設定する
6.出力ストリームを得て、すべての情報を出力する
7.転送結果を出力する
これで三つの方法が実現し、もつれた内容を積極的に実現する必要がある。
以上の方法は、いくつかのパラメータ情報を置き換えるだけで、完全に直接多重化できる。
今回は一つの問題に遭遇しました。これまで接触したことがない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.転送結果を出力する
これで三つの方法が実現し、もつれた内容を積極的に実現する必要がある。
以上の方法は、いくつかのパラメータ情報を置き換えるだけで、完全に直接多重化できる。