安卓上传图片

原理

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>
时间: 2024-10-08 10:28:01

安卓上传图片的相关文章

与安卓交互的上传图片 与 上传语音、视频

1.与安卓语音的交互 注意:获取语音的src 需要用DOM元素获取 (1)HTML (点击按钮告诉安卓,录音开始与结束) <span class="voice" onclick="voicecli()">上传语音</span> (2)JS //点击语音 function voicecli() { $('.addPicture').hide(); $('.expaddVoice').show(); //调方法 //判断调安卓方法显示或隐藏语音

微信上传图片

低版本的安卓上传图片是个问题,能出现选择图片,但点击图片后没有反应,转成base64也无解.于是改为用微信的接口上传.和之前的微信分享功能都是基于微信的jssdk. 步骤比我们平时上传到服务器多一步,他是先调用chooseeImage方法获得用户要上传的图片id.然后上传到微信的服务器,微信的服务器默认只保存三天,所以还要让后台下载到自己的服务器上,然后返回地址,前端显示,这样才算完成. var time = '@ViewBag.Share.timestamp'; wx.config({ deb

[javaSE] java上传图片给PHP

java通过http协议上传图片给php文件,对安卓上传图片给php接口的理解 java文件: import java.io.DataOutputStream; import java.io.File; import java.io.FileInputStream; import java.io.InputStream; import java.io.OutputStream; import java.net.HttpURLConnection; import java.net.URL; pub

安卓分段上传文件、视频

安卓上传图片的时候,还可以压缩, 但是上传视频的时候,没有好的压缩方式. 后来想到两种解决方式 1是用传统的http post 方式上传,传的内容是文件流,不过不知道承受力有多大,优点是这个方法已经成熟,传文件流,把传base64 处理过的,内存溢出情况少很多. 2是android 端,分段上传文件. 第二种是根本解决内存溢出方法 其核心思想是 1 同一个文件,分段上传上去采用相同的名字,后台把接收到的base64 数据拼接. 2 既然是分段,传完一段才能传下一段,并且完整拼接. 每个段都传完了

部分安卓手机微信浏览器中使用XMLHttpRequest 2上传图片显示字节数为0的解决办法

前端JS中使用XMLHttpRequest 2上传图片到服务器,PC端和大部分手机上都正常,但在少部分安卓手机上上传失败,服务器上查看图片,显示字节数为0.下面是上传图片的核心代码: HTML <input type="file" id="choose" capture="camera" accept="image/*"> JavaScript var filechooser = document.getEleme

关于安卓调用C#的WebService上传图片问题(不使用ksoap2)

============问题描述============ 小弟初学安卓开发.最近需要做一个图片上传的功能. 我是用java开发安卓,调用C#的WebService.在网上找到一大堆资料,几乎全部是用ksoap2包的. 请注意,我想做的是不用ksoap包的. 我现在的方法是从android端用读取到要上传的图片,用Base64编码成字节流的字符串,通过调用webservice把该字符串作为参数传到服务器端,服务端解码该字符串,最后保存到相应的路径下.整个上传过程的关键就是以字节流的字符串进行数据传

安卓无法上传图片的问题

首先上代码: 通过这种写法,在ios设备上确实是可以上传图片,但是在安卓系统中则无法上传,解决方法可以写成以下: <input @change="upImg(6)" ref="foreheadCir" type="file" accept="image/*" mutiple="mutiple" id="files" class="imageList"> 原

移动端web无刷新上传图片【兼容安卓IOS】

需求 手机端网页或者微信无刷新上传头像 环境 手机浏览器或者微信浏览器(支持HTML5) 实现方式 LocalResizeIMG 地址 https://github.com/think2011/LocalResizeIMG(原版地址) 链接: http://pan.baidu.com/s/1ntNYXrb 密码: 71cp(个人修改版) 说明 原版只能指定固定的图片宽度,而修改版扩展原图片上传 使用方式 <h1 class="text-center">LocalResize

使用最新最酷的安卓开发技术

首先开发工具当然不能用eclipse咯,当然得用android studio.api版本当然必须是23+,以支持cardview.receiveview.百分比布局等. 另外还有引入android support v7.android support design,这样界面的效果就不会太差了,也就是metal design的风格. 然后除了界面之外,还需要访问数据库,网络请求等. 对于数据库操作,android有相应的函数可以操作sqlite,不过默认的方式要用sql语句来操作,不是很方便快捷,