安卓上传图片 php服务器,Android 上传图片到服务器(PHP) 接受

原理

Android客户端模拟一个HTTP的Post请求到服务器端,服务器端接收相应的Post请求后,返回响应信息给给客户端。

PHP服务器

Android客户端

0818b9ca8b590ca3270a3433284dd417.png

0818b9ca8b590ca3270a3433284dd417.png

packagecom.example.uploadfile.app;importandroid.app.Activity;importandroid.os.Bundle;importandroid.os.Environment;importandroid.os.StrictMode;importandroid.view.View;importandroid.widget.Button;importandroid.widget.TextView;importandroid.widget.Toast;importjava.io.DataOutputStream;importjava.io.FileInputStream;importjava.io.InputStream;importjava.net.HttpURLConnection;importjava.net.URL;public class MainActivity extendsActivity

{private String fileName = "image.jpg"; //报文中的文件名参数

private String path = Environment.getExternalStorageDirectory().getPath(); //Don't use "/sdcard/" here

private String uploadFile = path + "/" + fileName; //待上传的文件路径

private String postUrl = "http://mycloudnote.sinaapp.com/upload.php"; //处理POST请求的页面

privateTextView mText1;privateTextView mText2;privateButton mButton;

@Overridepublic voidonCreate(Bundle savedInstanceState)

{super.onCreate(savedInstanceState);

setContentView(R.layout.activity_main);//"文件路径:\n"+

mText1 =(TextView) findViewById(R.id.myText1);

mText1.setText(uploadFile);//"上传网址:\n"+

mText2 =(TextView) findViewById(R.id.myText2);

mText2.setText(postUrl);/*设置mButton的onClick事件处理*/mButton=(Button) findViewById(R.id.myButton);

mButton.setOnClickListener(newView.OnClickListener()

{public voidonClick(View v)

{

uploadFile();

}

});

}/*上传文件至Server的方法*/

private voiduploadFile()

{

String end= "\r\n";

String twoHyphens= "--";

String boundary= "*****";try{

URL url= newURL(postUrl);

HttpURLConnection con=(HttpURLConnection) url.openConnection();/*Output to the connection. Default is false,

set to true because post method must write something to the connection*/con.setDoOutput(true);/*Read from the connection. Default is true.*/con.setDoInput(true);/*Post cannot use caches*/con.setUseCaches(false);/*Set the post method. Default is GET*/con.setRequestMethod("POST");/*设置请求属性*/con.setRequestProperty("Connection", "Keep-Alive");

con.setRequestProperty("Charset", "UTF-8");

con.setRequestProperty("Content-Type", "multipart/form-data;boundary=" +boundary);/*设置StrictMode 否则HTTPURLConnection连接失败,因为这是在主进程中进行网络连接*/StrictMode.setThreadPolicy(newStrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork().penaltyLog().build());/*设置DataOutputStream,getOutputStream中默认调用connect()*/DataOutputStream ds= new DataOutputStream(con.getOutputStream()); //output to the connection

ds.writeBytes(twoHyphens + boundary +end);

ds.writeBytes("Content-Disposition: form-data; " +

"name=\"file\";filename=\"" +fileName+ "\"" +end);

ds.writeBytes(end);/*取得文件的FileInputStream*/FileInputStream fStream= newFileInputStream(uploadFile);/*设置每次写入8192bytes*/

int bufferSize = 8192;byte[] buffer = new byte[bufferSize]; //8k

int length = -1;/*从文件读取数据至缓冲区*/

while ((length = fStream.read(buffer)) != -1)

{/*将资料写入DataOutputStream中*/ds.write(buffer,0, length);

}

ds.writeBytes(end);

ds.writeBytes(twoHyphens+ boundary + twoHyphens +end);/*关闭流,写入的东西自动生成Http正文*/fStream.close();/*关闭DataOutputStream*/ds.close();/*从返回的输入流读取响应信息*/InputStream is= con.getInputStream(); //input from the connection 正式建立HTTP连接

intch;

StringBuffer b= newStringBuffer();while ((ch = is.read()) != -1)

{

b.append((char) ch);

}/*显示网页响应内容*/Toast.makeText(MainActivity.this, b.toString().trim(), Toast.LENGTH_SHORT).show();//Post成功

} catch(Exception e)

{/*显示异常信息*/Toast.makeText(MainActivity.this, "Fail:" + e, Toast.LENGTH_SHORT).show();//Post失败

}

}

}

0818b9ca8b590ca3270a3433284dd417.png

设置连接(HTTP头) -> 建立TCP连接 -> 设置HTTP正文 -> 建立HTTP连接(正式Post)-> 从返回的输入流读取响应信息

1.设置连接(HTTP头)

0818b9ca8b590ca3270a3433284dd417.png

URL url = newURL(postUrl);

HttpURLConnection con=(HttpURLConnection) url.openConnection();/*Output to the connection. Default is false,

set to true because post method must write something to the connection*/con.setDoOutput(true);/*Read from the connection. Default is true.*/con.setDoInput(true);/*Post cannot use caches*/con.setUseCaches(false);/*Set the post method. Default is GET*/con.setRequestMethod("POST");/*设置请求属性*/con.setRequestProperty("Connection", "Keep-Alive");

con.setRequestProperty("Charset", "UTF-8");

con.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary);

0818b9ca8b590ca3270a3433284dd417.png

2.建立TCP连接

DataOutputStream ds = new DataOutputStream(con.getOutputStream()); //output to the connection

con.getOutputStream()中会默认调用con.connect(),此时客户端与服务器建立的只是1个TCP连接而非HTTP。

HTTP请求=HTTP头+HTTP正文。

在connect()里面,会根据HttpURLConnection对象的配置值生成HTTP头,所以对con的一切配置都必须在connect()方法之前完成。

3.设置HTTP正文

正文通过DataOutputStream写入,只是写入内存而不会发送到网络中去,而是在流关闭时,根据写入的内容生成HTTP正文。

0818b9ca8b590ca3270a3433284dd417.png

ds.writeBytes(twoHyphens + boundary +end);

ds.writeBytes("Content-Disposition: form-data; " +

"name=\"file\";filename=\"" +fileName+ "\"" +end);

ds.writeBytes(end);/*取得文件的FileInputStream*/FileInputStream fStream= newFileInputStream(uploadFile);/*设置每次写入8192bytes*/

int bufferSize = 8192;byte[] buffer = new byte[bufferSize]; //8k

int length = -1;/*从文件读取数据至缓冲区*/

while ((length = fStream.read(buffer)) != -1)

{/*将资料写入DataOutputStream中*/ds.write(buffer,0, length);

}

ds.writeBytes(end);

ds.writeBytes(twoHyphens+ boundary + twoHyphens +end);/*关闭流,写入的东西自动生成Http正文*/fStream.close();/*关闭DataOutputStream*/ds.close();

0818b9ca8b590ca3270a3433284dd417.png

4.建立HTTP连接(正式Post)

至此,HTTP请求设置完毕,con.getInputStream()中会将请求(HTTP头+HTTP正文)发送到服务器,并返回一个输入流。所以在getInputStream()之前,HTTP正文部分一定要先设置好。

InputStream is = con.getInputStream(); //input from the connection 正式建立HTTP连接

5.从返回的输入流读取响应信息

0818b9ca8b590ca3270a3433284dd417.png

intch;

StringBuffer b= newStringBuffer();while ((ch = is.read()) != -1)

{

b.append((char) ch);

}/*显示网页响应内容*/Toast.makeText(MainActivity.this, b.toString().trim(), Toast.LENGTH_SHORT).show();//Post成功

0818b9ca8b590ca3270a3433284dd417.png

布局XML

两个Text和一个Button

0818b9ca8b590ca3270a3433284dd417.png

View Code

AndroidManifest

添加网络权限、SD卡读写权限、挂载文件系统权限。

0818b9ca8b590ca3270a3433284dd417.png

View Code

注意事项

1.由于Android不建议在主进程中进行网络访问,所以使用HttpURLConnection连接到服务端时抛出异常,加入以下语句即可。

StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork().penaltyLog().build());

2.获取SD卡路径时,请使用Environment.getExternalStorageDirectory().getPath();而不是"/sdcard/"

另外几个个博客也很详细 :http://blog.csdn.net/caiwenfeng_for_23/article/details/47211745

http://www.jb51.net/article/77154.htm

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值