Android上传文件到服务器,通常采用构造http协议的方法,模拟网页POST方法传输文件,服务器端可以采用JavaServlet或者PHP来 接收要传输的文件。使用JavaServlet来接收文件的方法比较常见,在这里给大家介绍一个简单的服务器端使用PHP语言来接收文件的例子。
服务器端代码比较简单,接收传输过来的文件:
2 | $target_path = "./upload/" ; |
3 | $target_path = $target_path . basename ( $_FILES [ 'uploadedfile' ][ 'name' ]); |
4 | if (move_uploaded_file( $_FILES [ 'uploadedfile' ][ 'tmp_name' ], $target_path )) { |
5 | echo "The file " . basename ( $_FILES [ 'uploadedfile' ][ 'name' ]). " has been uploaded" ; |
7 | echo "There was an error uploading the file, please try again!" . $_FILES [ 'uploadedfile' ][ 'error' ]; |
手机客户端代码:
001 | package com.figo.uploadfile; |
003 | import java.io.BufferedReader; |
004 | import java.io.DataOutputStream; |
005 | import java.io.FileInputStream; |
006 | import java.io.InputStream; |
007 | import java.io.InputStreamReader; |
008 | import java.net.HttpURLConnection; |
010 | import android.app.Activity; |
011 | import android.os.Bundle; |
012 | import android.view.View; |
013 | import android.widget.Button; |
014 | import android.widget.TextView; |
015 | import android.widget.Toast; |
017 | public class UploadfileActivity extends Activity |
020 | private String uploadFile = "/sdcard/testimg.jpg" ; |
021 | private String srcPath = "/sdcard/testimg.jpg" ; |
023 | private String actionUrl = "http://10.100.1.208/receive_file.php" ; |
024 | private TextView mText1; |
025 | private TextView mText2; |
026 | private Button mButton; |
029 | public void onCreate(Bundle savedInstanceState) |
031 | super .onCreate(savedInstanceState); |
032 | setContentView(R.layout.main); |
034 | mText1 = (TextView) findViewById(R.id.myText2); |
035 | mText1.setText( "文件路径:\n" + uploadFile); |
036 | mText2 = (TextView) findViewById(R.id.myText3); |
037 | mText2.setText( "上传网址:\n" + actionUrl); |
051 | private void uploadFile(String uploadUrl) |
054 | String twoHyphens = "--" ; |
055 | String boundary = "******" ; |
058 | URL url = new URL(uploadUrl); |
059 | HttpURLConnection httpURLConnection = (HttpURLConnection) url |
063 | httpURLConnection.setChunkedStreamingMode( 128 * 1024 ); |
065 | httpURLConnection.setDoInput( true ); |
066 | httpURLConnection.setDoOutput( true ); |
067 | httpURLConnection.setUseCaches( false ); |
069 | httpURLConnection.setRequestMethod( "POST" ); |
070 | httpURLConnection.setRequestProperty( "Connection" , "Keep-Alive" ); |
071 | httpURLConnection.setRequestProperty( "Charset" , "UTF-8" ); |
072 | httpURLConnection.setRequestProperty( "Content-Type" , |
073 | "multipart/form-data;boundary=" + boundary); |
075 | DataOutputStream dos = new DataOutputStream( |
076 | httpURLConnection.getOutputStream()); |
077 | dos.writeBytes(twoHyphens + boundary + end); |
078 | dos.writeBytes( "Content-Disposition: form-data; name=\"uploadedfile\"; filename=\"" |
079 | + srcPath.substring(srcPath.lastIndexOf( "/" ) + 1 ) |
084 | FileInputStream fis = new FileInputStream(srcPath); |
085 | byte [] buffer = new byte [ 8192 ]; |
088 | while ((count = fis.read(buffer)) != - 1 ) |
090 | dos.write(buffer, 0 , count); |
095 | dos.writeBytes(twoHyphens + boundary + twoHyphens + end); |
098 | InputStream is = httpURLConnection.getInputStream(); |
099 | InputStreamReader isr = new InputStreamReader(is, "utf-8" ); |
100 | BufferedReader br = new BufferedReader(isr); |
101 | String result = br.readLine(); |
103 | Toast.makeText( this , result, Toast.LENGTH_LONG).show(); |
107 | } catch (Exception e) |
110 | setTitle(e.getMessage()); |
在AndroidManifest.xml文件里添加网络访问权限:
1 | < uses-permission android:name = "android.permission.INTERNET" /> |
运行结果:
以上已经能够实现文件上传,但没有上传进度。这次在之前的基础上添加进度显示,Java代码如下所示:
001 | package com.lenovo.uptest; |
003 | import java.io.DataInputStream; |
004 | import java.io.DataOutputStream; |
006 | import java.io.FileInputStream; |
007 | import java.net.HttpURLConnection; |
010 | import android.app.Activity; |
011 | import android.app.AlertDialog; |
012 | import android.app.ProgressDialog; |
013 | import android.content.DialogInterface; |
014 | import android.os.AsyncTask; |
015 | import android.os.Bundle; |
016 | import android.view.View; |
017 | import android.widget.Button; |
018 | import android.widget.TextView; |
020 | public class UploadtestActivity extends Activity { |
021 | /** Called when the activity is first created. */ |
023 | * Upload file to web server with progress status, client: android; |
027 | private TextView mtv1 = null ; |
028 | private TextView mtv2 = null ; |
029 | private Button bupload = null ; |
031 | private String uploadFile = "/sdcard/testimg.jpg" ; |
032 | private String actionUrl = "http://10.100.1.208/receive_file.php" ; |
035 | public void onCreate(Bundle savedInstanceState) { |
036 | super .onCreate(savedInstanceState); |
037 | setContentView(R.layout.main); |
039 | mtv1 = (TextView) findViewById(R.id.mtv1); |
040 | mtv1.setText( "文件路径:\n" + uploadFile); |
041 | mtv2 = (TextView) findViewById(R.id.mtv2); |
042 | mtv2.setText( "上传地址:\n" + actionUrl); |
043 | bupload = (Button) findViewById(R.id.bupload); |
044 | bupload.setOnClickListener( new View.OnClickListener() { |
047 | public void onClick(View v) { |
049 | FileUploadTask fileuploadtask = new FileUploadTask(); |
050 | fileuploadtask.execute(); |
056 | private void showDialog(String mess) { |
057 | new AlertDialog.Builder(UploadtestActivity. this ).setTitle( "Message" ) |
059 | .setNegativeButton( "确定" , new DialogInterface.OnClickListener() { |
061 | public void onClick(DialogInterface dialog, int which) { |
066 | class FileUploadTask extends AsyncTask<Object, Integer, Void> { |
068 | private ProgressDialog dialog = null ; |
069 | HttpURLConnection connection = null ; |
070 | DataOutputStream outputStream = null ; |
071 | DataInputStream inputStream = null ; |
073 | String pathToOurFile = "/sdcard/testimg.jpg" ; |
075 | String urlServer = "http://10.100.1.208/receive_file.php" ; |
076 | String lineEnd = "\r\n" ; |
077 | String twoHyphens = "--" ; |
078 | String boundary = "*****" ; |
080 | File uploadFile = new File(pathToOurFile); |
081 | long totalSize = uploadFile.length(); |
084 | protected void onPreExecute() { |
085 | dialog = new ProgressDialog(UploadtestActivity. this ); |
086 | dialog.setMessage( "正在上传..." ); |
087 | dialog.setIndeterminate( false ); |
088 | dialog.setProgressStyle(ProgressDialog.STYLE_HORIZONTAL); |
089 | dialog.setProgress( 0 ); |
094 | protected Void doInBackground(Object... arg0) { |
098 | int bytesRead, bytesAvailable, bufferSize; |
100 | int maxBufferSize = 256 * 1024 ; |
103 | FileInputStream fileInputStream = new FileInputStream( new File( |
106 | URL url = new URL(urlServer); |
107 | connection = (HttpURLConnection) url.openConnection(); |
110 | connection.setChunkedStreamingMode( 256 * 1024 ); |
113 | connection.setDoInput( true ); |
114 | connection.setDoOutput( true ); |
115 | connection.setUseCaches( false ); |
118 | connection.setRequestMethod( "POST" ); |
119 | connection.setRequestProperty( "Connection" , "Keep-Alive" ); |
120 | connection.setRequestProperty( "Charset" , "UTF-8" ); |
121 | connection.setRequestProperty( "Content-Type" , |
122 | "multipart/form-data;boundary=" + boundary); |
124 | outputStream = new DataOutputStream( |
125 | connection.getOutputStream()); |
126 | outputStream.writeBytes(twoHyphens + boundary + lineEnd); |
128 | .writeBytes( "Content-Disposition: form-data; name=\"uploadedfile\";filename=\"" |
129 | + pathToOurFile + "\"" + lineEnd); |
130 | outputStream.writeBytes(lineEnd); |
132 | bytesAvailable = fileInputStream.available(); |
133 | bufferSize = Math.min(bytesAvailable, maxBufferSize); |
134 | buffer = new byte [bufferSize]; |
137 | bytesRead = fileInputStream.read(buffer, 0 , bufferSize); |
139 | while (bytesRead > 0 ) { |
140 | outputStream.write(buffer, 0 , bufferSize); |
141 | length += bufferSize; |
142 | progress = ( int ) ((length * 100 ) / totalSize); |
143 | publishProgress(progress); |
145 | bytesAvailable = fileInputStream.available(); |
146 | bufferSize = Math.min(bytesAvailable, maxBufferSize); |
147 | bytesRead = fileInputStream.read(buffer, 0 , bufferSize); |
149 | outputStream.writeBytes(lineEnd); |
150 | outputStream.writeBytes(twoHyphens + boundary + twoHyphens |
152 | publishProgress( 100 ); |
155 | int serverResponseCode = connection.getResponseCode(); |
156 | String serverResponseMessage = connection.getResponseMessage(); |
173 | fileInputStream.close(); |
174 | outputStream.flush(); |
175 | outputStream.close(); |
177 | } catch (Exception ex) { |
189 | protected void onProgressUpdate(Integer... progress) { |
190 | dialog.setProgress(progress[ 0 ]); |
194 | protected void onPostExecute(Void result) { |
198 | } 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传入的参数。
运行结果如下: