Android上传图片(PHP服务器)
原理
Android客户端模拟一个HTTP的Post请求到服务器端,服务器端接收相应的Post请求后,返回响应信息给给客户端。
PHP服务器
<?php
move_uploaded_file($_FILES['file']['tmp_name'], "./upload/".$_FILES["file"]["name"]);
?>
Android客户端
package com.example.uploadfile.app; import android.app.Activity;
import android.os.Bundle;
import android.os.Environment;
import android.os.StrictMode;
import android.view.View;
import android.widget.Button;
import android.widget.TextView;
import android.widget.Toast; import java.io.DataOutputStream;
import java.io.FileInputStream;
import java.io.InputStream;
import java.net.HttpURLConnection;
import java.net.URL; public class MainActivity extends Activity
{
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请求的页面
private TextView mText1;
private TextView mText2;
private Button mButton; @Override
public void onCreate(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(new View.OnClickListener()
{
public void onClick(View v)
{
uploadFile();
}
});
} /* 上传文件至Server的方法 */
private void uploadFile()
{
String end = "\r\n";
String twoHyphens = "--";
String boundary = "*****";
try
{
URL url = new URL(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(new StrictMode.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 = new FileInputStream(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连接
int ch;
StringBuffer b = new StringBuffer();
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失败
}
}
}
设置连接(HTTP头) -> 建立TCP连接 -> 设置HTTP正文 -> 建立HTTP连接(正式Post)-> 从返回的输入流读取响应信息
1.设置连接(HTTP头)
URL url = new URL(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);
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正文。
ds.writeBytes(twoHyphens + boundary + end);
ds.writeBytes("Content-Disposition: form-data; " +
"name=\"file\";filename=\"" +
fileName + "\"" + end);
ds.writeBytes(end);
/* 取得文件的FileInputStream */
FileInputStream fStream = new FileInputStream(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();
4.建立HTTP连接(正式Post)
至此,HTTP请求设置完毕,con.getInputStream()中会将请求(HTTP头+HTTP正文)发送到服务器,并返回一个输入流。所以在getInputStream()之前,HTTP正文部分一定要先设置好。
InputStream is = con.getInputStream(); //input from the connection 正式建立HTTP连接
5.从返回的输入流读取响应信息
int ch;
StringBuffer b = new StringBuffer();
while ((ch = is.read()) != -1)
{
b.append((char) ch);
}
/* 显示网页响应内容 */
Toast.makeText(MainActivity.this, b.toString().trim(), Toast.LENGTH_SHORT).show();//Post成功
布局XML
两个Text和一个Button
<RelativeLayout xmlns:android="http://schemas.android.com/apk/res/android"
xmlns:tools="http://schemas.android.com/tools"
android:layout_width="match_parent"
android:layout_height="match_parent"
tools:context="${packageName}.${activityClass}"> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Text"
android:id="@+id/myText1"
android:layout_above="@+id/myText2"
android:layout_centerHorizontal="true"
android:layout_marginBottom="80dp"/> <TextView
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="New Text"
android:id="@+id/myText2"
android:layout_centerVertical="true"
android:layout_centerHorizontal="true"/> <Button
android:layout_width="wrap_content"
android:layout_height="wrap_content"
android:text="Upload"
android:id="@+id/myButton"
android:layout_marginTop="80dp"
android:layout_below="@+id/myText2"
android:layout_centerHorizontal="true"/>
</RelativeLayout>
AndroidManifest
添加网络权限、SD卡读写权限、挂载文件系统权限。
<?xml version="1.0" encoding="utf-8"?>
<manifest xmlns:android="http://schemas.android.com/apk/res/android"
package="com.example.uploadfile.app" > <application
android:allowBackup="true"
android:icon="@drawable/ic_launcher"
android:label="@string/app_name"
android:theme="@style/AppTheme" >
<activity
android:name="com.example.uploadfile.app.MainActivity"
android:label="@string/app_name" >
<intent-filter>
<action android:name="android.intent.action.MAIN" /> <category android:name="android.intent.category.LAUNCHER" />
</intent-filter>
</activity>
</application>
<uses-sdk android:minSdkVersion="9" android:targetSdkVersion="15" />
<uses-permission android:name="android.permission.INTERNET" />
<uses-permission android:name="android.permission.WRITE_EXTERNAL_STORAGE"/>
<uses-permission android:name="android.permission.MOUNT_UNMOUNT_FILESYSTEMS"/>
</manifest>
注意事项
1.由于Android不建议在主进程中进行网络访问,所以使用HttpURLConnection连接到服务端时抛出异常,加入以下语句即可。
StrictMode.setThreadPolicy(new StrictMode.ThreadPolicy.Builder().detectDiskReads().detectDiskWrites().detectNetwork().penaltyLog().build());
2.获取SD卡路径时,请使用Environment.getExternalStorageDirectory().getPath();而不是"/sdcard/"
参考文章
【Android开发那点破事】解决Andriod使用HttpURLConnection 失败问题
Android上传图片(PHP服务器)的更多相关文章
- Android 上传图片到服务器二--------调用相机7.0以上权限问题
[目录] (一)上传图片到服务器一 ---------------------------------Android代码 (二)上传图片到服务器二--------------------------- ...
- Android 上传图片到服务器 okhttp一
[目录] (一)上传图片到服务器一 ---------------------------------Android代码 (二)上传图片到服务器二--------------------------- ...
- Android上传图片到服务器
一.android需要导入异步请求的jar包 AsyncHttpClient public static void reg(final Context cont,Bitmap photodata,S ...
- android 上传图片到服务器Tomcat(Struts2)
在做android开发的时候,有时你会用到图片的上传功能,在我的android项目中,我是选中图片,点击上传多张图片 android客户端上传图片部分的代码如下: package com.exampl ...
- android上传图片至服务器
本实例实现了android上传手机图片至服务器,服务器进行保存 服务器servlet代码publicvoid doPost(HttpServletRequest request, HttpServle ...
- Android上传图片到服务器,服务端利用.NET WCFRest服务读取文件的解决方案
在项目中遇到要将Android设备拍摄的照片上传的服务器,将文件保存在服务器本地的文件夹中,数据库中保存的是图片文件名.整个上传是将图片生成二进制流通过HTTP请求上传到服务端,服务端是基于.NET环 ...
- 通过android 客户端上传图片到服务器
昨天,(在我的上一篇博客中)写了通过浏览器上传图片到服务器(php),今天将这个功能付诸实践.(还完善了服务端的代码) 不试不知道,原来通过android 向服务端发送图片还真是挺麻烦的一件事. 上传 ...
- Android客户端与服务器
就是普通的服务器端编程,还不用写界面,其实还比服务器编程简单一些.跟J2EE一样的服务器,你android这一方面只要用json或者gson直接拿数据,后台的话用tomcat接受请求操作数据,功能不复 ...
- 【Android】与服务器实现JSON数据通信
一.前言 作为一名移动端开发人员,具备一定的服务端开发能力也是非常必要的,本篇博客讲述如何在Android和服务器之间实现JSON数据通信交互,博客内容基于另外一篇博客:[Web]Eclipse + ...
- Wcf for wp8 上传图片到服务器,将图片名字插入数据库字段(五)
环境:.NET Framework 3.5 服务: IIS EXpress托管 WCF服务程序 配置:Web.config <!--<connectionStrings> <a ...
随机推荐
- (一)Solr——简介和安装配置
1. solr简介 1.1 Solr是什么 Solr是apache的顶级开源项目,它是使用java开发 ,基于lucene的全文检索服务器. Solr和lucene的版本是同步更新的,最新的版本是7. ...
- lsb_release: command not found 解决
问题:lsb_release 是查看系统版本信息的工具 [root@localhost ~]# lsb_release -a-bash: lsb_release: command not found ...
- Codeigniter 使用 Mysql 存储过程
本篇文章由:http://xinpure.com/codeigniter-using-mysql-stored-procedures/ 执行存储过程 $query = $this -> db - ...
- 表格行与行的间距设置,通过margin无效,要这么设置
CSS border-collapse 属性设置表格的边框是否被合并为一个单一的边框 值 描述 separate 默认值.边框会被分开.不会忽略 border-spacing 和 empty-cell ...
- HIVE的transform函数的使用
Hive的TRANSFORM关键字提供了在SQL中调用自写脚本的功能,适合实现Hive中没有的功能又不想写UDF的情况.例如,按日期统计每天出现的uid数,通常用如下的SQL SELECT date, ...
- 远程调试 Weinre
什么是远程调试? 说白了,就是可以通过PC端[F12开发者工具]查看并调试移动端的页面内容,如html.css.js.Network资源等. 重要的事情说三遍:weinre所占有的端口不需要和监听页面 ...
- IOS 拍照旋转修正
- (UIImage *)fixOrientation:(UIImage *)aImage { // No-op if the orientation is already correct if (a ...
- mysql操作索引的sql语句
创建索引 一:唯一索引alter table table_name add unique index_name(column_list); 例如:alter table users_game_task ...
- atitit。全局变量的设计与实现 java php的异同
atitit.全局变量的设计与实现 java php的异同 1. 超级全局(Superglobals)"变量 1 2. 全局变量和"global"关键字 1 3. 更加好 ...
- 快速解读GC日志
本文是 Plumbr 发行的 Java垃圾收集指南 的部分内容.文中将介绍GC日志的输出格式, 以及如何解读GC日志, 从中提取有用的信息.我们通过 -XX:+UseSerialGC 选项,指定JVM ...