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/"

参考文章

HttpURLConnection学习

Android上传文件到Web服务器,PHP接收文件(一)

【Android开发那点破事】解决Andriod使用HttpURLConnection 失败问题

Android上传图片(PHP服务器),布布扣,bubuko.com

时间: 2024-10-29 12:17:51

Android上传图片(PHP服务器)的相关文章

android上传图片至服务器

本实例实现了android上传手机图片至服务器,服务器进行保存 服务器servlet代码publicvoid doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException { String temp=request.getSession().getServletContext().getRealPath("/")+"temp"

android 上传图片到服务器Tomcat(Struts2)

在做android开发的时候,有时你会用到图片的上传功能,在我的android项目中,我是选中图片,点击上传多张图片 android客户端上传图片部分的代码如下: package com.example.myphotos.utils; import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.IOException; import java.io.Inp

Android上传图片到服务器

一.android需要导入异步请求的jar包 AsyncHttpClient  public static void reg(final Context cont,Bitmap photodata,String regData) { try { ByteArrayOutputStream baos = new ByteArrayOutputStream(); //将bitmap一字节流输出 Bitmap.CompressFormat.PNG 压缩格式,100:压缩率,baos:字节流 photo

android上传图片到服务器(使用base64字节流的形式通过 AsyncHttpClient框架

前端 andoid  activity用到的函数 AsyncHttpClient  是一个框架提供的库  可以异步传输,使用时需下载android-async-http-1.4.4.jar包导入到项目中 [java]  view plain copy public static void reg(final Context cont,Bitmap photodata,String regData) { try { ByteArrayOutputStream baos = new ByteArra

通过android 客户端上传图片到服务器

昨天,(在我的上一篇博客中)写了通过浏览器上传图片到服务器(php),今天将这个功能付诸实践.(还完善了服务端的代码) 不试不知道,原来通过android 向服务端发送图片还真是挺麻烦的一件事. 上传代码: /* 上传文件至Server的方法 */ private void uploadFile() { String end = "\r\n"; String twoHyphens = "--"; String boundary = "*****"

从相册获取图片及调用相机拍照获取图片,最后上传图片到服务器

调用相机拍照获取图片: 跳转到到拍照界面: Intent takeIntent = new Intent(MediaStore.ACTION_IMAGE_CAPTURE); //下面这句指定调用相机拍照后的照片存储的路径 mSzImageFileName = Long.toString(System.currentTimeMillis()) + ".png"; takeIntent.putExtra(MediaStore.EXTRA_OUTPUT, Uri.fromFile(new F

Android上传图片之调用系统拍照和从相册选择图片

Android上传图片之调用系统拍照和从相册选择图片 前言: 万丈高楼平底起,万事起于微末.不知不觉距离上篇博文已近四个月,2015年12月17日下午发了第一篇博文,现在是2016年4月6日.时间间隔长的过分啊,我自己都看不下去了.原因呢?当然是自己的原因,其实是有很多时间来些博客的,但是这些时间都花在DOTA上了(还是太年轻啊).请原谅我的过错--. 一.概述: 现在几乎应用都会用到上传图片的功能,而要上传图片,首先得选择图片,本文不针对如何上传图片到服务器(每个项目与服务器交互的方式不同,因

【Android】与服务器实现JSON数据通信

一.前言 作为一名移动端开发人员,具备一定的服务端开发能力也是非常必要的,本篇博客讲述如何在Android和服务器之间实现JSON数据通信交互,博客内容基于另外一篇博客:[Web]Eclipse + Maven + Struts搭建服务器. 二.服务器端改造 在博客[Web]Eclipse + Maven + Struts搭建服务器中,我们实现了服务器的搭建,现在要做的事情就是让它返回的数据是一个JSON格式的,这样在获得请求的时候,我们才可以得到JSON数据,其配置改变如下. 首先我们新建一个

Android客户端与服务器交互方式-小结

最近的Android项目开发过程中一个问题困扰自己很长时间,Android客户端与服务器交互有几种方式,最常见的就是webservices和json.要在Android手机客户端与pc服务器交互,需要满足下面几种条件:跨平台.传输数据格式标准.交互方便. 为了与服务器通讯其实无非就两种协议HTTP和TCP,TCP的学习Socket,HTTP的话熟悉一下HTTP协议和相关Java API.而下面的几种方式就是从这两种协议扩展出来的:webservices soap.SSH的JSON(可参考:该链接