Android上传文件到服务器,通常采用构造http协议的方法,模拟网页POST方法传输文件,服务器端可以采用JavaServlet或者PHP来 接收要传输的文件。使用JavaServlet来接收文件的方法比较常见,在这里给大家介绍一个简单的服务器端使用PHP语言来接收文件的例子。
服务器端代码比较简单,接收传输过来的文件:
1
2
3
4
5
6
7
8
9
|
<?php
$target_path
=
"./upload/"
;
//接收文件目录
$target_path
=
$target_path
.
basename
(
$_FILES
[
'uploadedfile'
][
'name'
]);
if
(move_uploaded_file(
$_FILES
[
'uploadedfile'
][
'tmp_name'
],
$target_path
)) {
echo
"The file "
.
basename
(
$_FILES
[
'uploadedfile'
][
'name'
]).
" has been uploaded"
;
}
else
{
echo
"There was an error uploading the file, please try again!"
.
$_FILES
[
'uploadedfile'
][
'error'
];
}
?>
|
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
|
package
com.figo.uploadfile;
import
java.io.BufferedReader;
import
java.io.DataOutputStream;
import
java.io.FileInputStream;
import
java.io.InputStream;
import
java.io.InputStreamReader;
import
java.net.HttpURLConnection;
import
java.net.URL;
import
android.app.Activity;
import
android.os.Bundle;
import
android.view.View;
import
android.widget.Button;
import
android.widget.TextView;
import
android.widget.Toast;
public
class
UploadfileActivity
extends
Activity
{
// 要上传的文件路径,理论上可以传输任何文件,实际使用时根据需要处理
private
String uploadFile =
"/sdcard/testimg.jpg"
;
private
String srcPath =
"/sdcard/testimg.jpg"
;
// 服务器上接收文件的处理页面,这里根据需要换成自己的
private
String actionUrl =
"http://10.100.1.208/receive_file.php"
;
private
TextView mText1;
private
TextView mText2;
private
Button mButton;
@Override
public
void
onCreate(Bundle savedInstanceState)
{
super
.onCreate(savedInstanceState);
setContentView(R.layout.main);
mText1 = (TextView) findViewById(R.id.myText2);
mText1.setText(
"文件路径:\n"
+ uploadFile);
mText2 = (TextView) findViewById(R.id.myText3);
mText2.setText(
"上传网址:\n"
+ actionUrl);
/* 设置mButton的onClick事件处理 */
mButton = (Button) findViewById(R.id.myButton);
mButton.setOnClickListener(new View.OnClickListener()
{
@Override
public void onClick(View v)
{
uploadFile(actionUrl);
}
});
}
/* 上传文件至Server,uploadUrl:接收文件的处理页面 */
private
void
uploadFile(String uploadUrl)
{
String end =
"\r\n"
;
String twoHyphens =
"--"
;
String boundary =
"******"
;
try
{
URL url =
new
URL(uploadUrl);
HttpURLConnection httpURLConnection = (HttpURLConnection) url
.openConnection();
// 设置每次传输的流大小,可以有效防止手机因为内存不足崩溃
// 此方法用于在预先不知道内容长度时启用没有进行内部缓冲的 HTTP 请求正文的流。
httpURLConnection.setChunkedStreamingMode(
128
*
1024
);
// 128K
// 允许输入输出流
httpURLConnection.setDoInput(
true
);
httpURLConnection.setDoOutput(
true
);
httpURLConnection.setUseCaches(
false
);
// 使用POST方法
httpURLConnection.setRequestMethod(
"POST"
);
httpURLConnection.setRequestProperty(
"Connection"
,
"Keep-Alive"
);
httpURLConnection.setRequestProperty(
"Charset"
,
"UTF-8"
);
httpURLConnection.setRequestProperty(
"Content-Type"
,
"multipart/form-data;boundary="
+ boundary);
DataOutputStream dos =
new
DataOutputStream(
httpURLConnection.getOutputStream());
dos.writeBytes(twoHyphens + boundary + end);
dos.writeBytes(
"Content-Disposition: form-data; name=\"uploadedfile\"; filename=\""
+ srcPath.substring(srcPath.lastIndexOf(
"/"
) +
1
)
+
"\""
+ end);
dos.writeBytes(end);
FileInputStream fis =
new
FileInputStream(srcPath);
byte
[] buffer =
new
byte
[
8192
];
// 8k
int
count =
0
;
// 读取文件
while
((count = fis.read(buffer)) != -
1
)
{
dos.write(buffer,
0
, count);
}
fis.close();
dos.writeBytes(end);
dos.writeBytes(twoHyphens + boundary + twoHyphens + end);
dos.flush();
InputStream is = httpURLConnection.getInputStream();
InputStreamReader isr =
new
InputStreamReader(is,
"utf-8"
);
BufferedReader br =
new
BufferedReader(isr);
String result = br.readLine();
Toast.makeText(
this
, result, Toast.LENGTH_LONG).show();
dos.close();
is.close();
}
catch
(Exception e)
{
e.printStackTrace();
setTitle(e.getMessage());
}
}
}
|
1
|
<
uses-permission
android:name
=
"android.permission.INTERNET"
/>
|
运行结果:
以上已经能够实现文件上传,但没有上传进度。这次在之前的基础上添加进度显示,Java代码如下所示:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
|
package
com.lenovo.uptest;
import
java.io.DataInputStream;
import
java.io.DataOutputStream;
import
java.io.File;
import
java.io.FileInputStream;
import
java.net.HttpURLConnection;
import
java.net.URL;
import
android.app.Activity;
import
android.app.AlertDialog;
import
android.app.ProgressDialog;
import
android.content.DialogInterface;
import
android.os.AsyncTask;
import
android.os.Bundle;
import
android.view.View;
import
android.widget.Button;
import
android.widget.TextView;
public
class
UploadtestActivity
extends
Activity {
/** Called when the activity is first created. */
/**
* Upload file to web server with progress status, client: android;
* server:php
* **/
private
TextView mtv1 =
null
;
private
TextView mtv2 =
null
;
private
Button bupload =
null
;
private
String uploadFile =
"/sdcard/testimg.jpg"
;
private
String actionUrl =
"http://10.100.1.208/receive_file.php"
;
@Override
public
void
onCreate(Bundle savedInstanceState) {
super
.onCreate(savedInstanceState);
setContentView(R.layout.main);
mtv1 = (TextView) findViewById(R.id.mtv1);
mtv1.setText(
"文件路径:\n"
+ uploadFile);
mtv2 = (TextView) findViewById(R.id.mtv2);
mtv2.setText(
"上传地址:\n"
+ actionUrl);
bupload = (Button) findViewById(R.id.bupload);
bupload.setOnClickListener(
new
View.OnClickListener() {
@Override
public
void
onClick(View v) {
// TODO Auto-generated method stub
FileUploadTask fileuploadtask =
new
FileUploadTask();
fileuploadtask.execute();
}
});
}
// show Dialog method
private
void
showDialog(String mess) {
new
AlertDialog.Builder(UploadtestActivity.
this
).setTitle(
"Message"
)
.setMessage(mess)
.setNegativeButton(
"确定"
,
new
DialogInterface.OnClickListener() {
@Override
public
void
onClick(DialogInterface dialog,
int
which) {
}
}).show();
}
class
FileUploadTask
extends
AsyncTask<Object, Integer, Void> {
private
ProgressDialog dialog =
null
;
HttpURLConnection connection =
null
;
DataOutputStream outputStream =
null
;
DataInputStream inputStream =
null
;
//the file path to upload
String pathToOurFile =
"/sdcard/testimg.jpg"
;
//the server address to process uploaded file
String urlServer =
"http://10.100.1.208/receive_file.php"
;
String lineEnd =
"\r\n"
;
String twoHyphens =
"--"
;
String boundary =
"*****"
;
File uploadFile =
new
File(pathToOurFile);
long
totalSize = uploadFile.length();
// Get size of file, bytes
@Override
protected
void
onPreExecute() {
dialog =
new
ProgressDialog(UploadtestActivity.
this
);
dialog.setMessage(
"正在上传..."
);
dialog.setIndeterminate(
false
);
dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL);
dialog.setProgress(
0
);
dialog.show();
}
@Override
protected
Void doInBackground(Object... arg0) {
long
length =
0
;
int
progress;
int
bytesRead, bytesAvailable, bufferSize;
byte
[] buffer;
int
maxBufferSize =
256
*
1024
;
// 256KB
try
{
FileInputStream fileInputStream =
new
FileInputStream(
new
File(
pathToOurFile));
URL url =
new
URL(urlServer);
connection = (HttpURLConnection) url.openConnection();
// Set size of every block for post
connection.setChunkedStreamingMode(
256
*
1024
);
// 256KB
// Allow Inputs & Outputs
connection.setDoInput(
true
);
connection.setDoOutput(
true
);
connection.setUseCaches(
false
);
// Enable POST method
connection.setRequestMethod(
"POST"
);
connection.setRequestProperty(
"Connection"
,
"Keep-Alive"
);
connection.setRequestProperty(
"Charset"
,
"UTF-8"
);
connection.setRequestProperty(
"Content-Type"
,
"multipart/form-data;boundary="
+ boundary);
outputStream =
new
DataOutputStream(
connection.getOutputStream());
outputStream.writeBytes(twoHyphens + boundary + lineEnd);
outputStream
.writeBytes(
"Content-Disposition: form-data; name=\"uploadedfile\";filename=\""
+ pathToOurFile +
"\""
+ lineEnd);
outputStream.writeBytes(lineEnd);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
buffer =
new
byte
[bufferSize];
// Read file
bytesRead = fileInputStream.read(buffer,
0
, bufferSize);
while
(bytesRead >
0
) {
outputStream.write(buffer,
0
, bufferSize);
length += bufferSize;
progress = (
int
) ((length *
100
) / totalSize);
publishProgress(progress);
bytesAvailable = fileInputStream.available();
bufferSize = Math.min(bytesAvailable, maxBufferSize);
bytesRead = fileInputStream.read(buffer,
0
, bufferSize);
}
outputStream.writeBytes(lineEnd);
outputStream.writeBytes(twoHyphens + boundary + twoHyphens
+ lineEnd);
publishProgress(
100
);
// Responses from the server (code and message)
int
serverResponseCode = connection.getResponseCode();
String serverResponseMessage = connection.getResponseMessage();
/* 将Response显示于Dialog */
// Toast toast = Toast.makeText(UploadtestActivity.this, ""
// + serverResponseMessage.toString().trim(),
// Toast.LENGTH_LONG);
// showDialog(serverResponseMessage.toString().trim());
/* 取得Response内容 */
// InputStream is = connection.getInputStream();
// int ch;
// StringBuffer sbf = new StringBuffer();
// while ((ch = is.read()) != -1) {
// sbf.append((char) ch);
// }
//
// showDialog(sbf.toString().trim());
fileInputStream.close();
outputStream.flush();
outputStream.close();
}
catch
(Exception ex) {
// Exception handling
// showDialog("" + ex);
// Toast toast = Toast.makeText(UploadtestActivity.this, "" +
// ex,
// Toast.LENGTH_LONG);
}
return
null
;
}
@Override
protected
void
onProgressUpdate(Integer... progress) {
dialog.setProgress(progress[
0
]);
}
@Override
protected
void
onPostExecute(Void result) {
try
{
dialog.dismiss();
// TODO Auto-generated method stub
}
catch
(Exception e) {
}
}
}
}
|
服务器端仍然和之前的一样。
这里使用了AsyncTask,它使创建需要与用户界面交互的长时间运行的任务变得更简单,适用于简单的异步处理,不需要借助线程和Handler即可实现。
AsyncTask是抽象类.AsyncTask定义了三种泛型类型 Params,Progress和Result。
Params 启动任务执行的输入参数,比如HTTP请求的URL。
Progress 后台任务执行的百分比。
Result 后台执行任务最终返回的结果,比如String。
AsyncTask的执行分为四个步骤,每一步都对应一个回调方法,这些方法不应该由应用程序调用,开发者需要做的就是实现这些方法。
1) 子类化AsyncTask
2) 实现AsyncTask中定义的下面一个或几个方法
onPreExecute(), 该方法将在执行实际的后台操作前被UI thread调用。可以在该方法中做一些准备工作,如在界面上显示一个进度条。
doInBackground(Params...), 将在onPreExecute 方法执行后马上执行,该方法运行在后台线程中。这里将主要负责执行那些很耗时的后台计算工作。可以调用 publishProgress方法来更新实时的任务进度。该方法是抽象方法,子类必须实现。
onProgressUpdate(Progress...),在publishProgress方法被调用后,UI thread将调用这个方法从而在界面上展示任务的进展情况,例如通过一个进度条进行展示。
onPostExecute(Result), 在doInBackground 执行完成后,onPostExecute 方法将被UI thread调用,后台的计算结果将通过该方法传递到UI thread.
为了正确的使用AsyncTask类,以下是几条必须遵守的准则:
1) Task的实例必须在UI thread中创建
2) execute方法必须在UI thread中调用
3) 不要手动的调用onPreExecute(), onPostExecute(Result),doInBackground(Params...), onProgressUpdate(Progress...)这几个方法
4) 该task只能被执行一次,否则多次调用时将会出现异常
doInBackground方法和onPostExecute的参数必须对应,这两个参数在AsyncTask声明的泛型参数列表中指定,第一个为 doInBackground接受的参数,第二个为显示进度的参数,第三个为doInBackground返回和onPostExecute传入的参数。
运行结果如下:
转自:http://blog.csdn.net/sxwyf248/article/details/7012758