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

昨天,(在我的上一篇博客中)写了通过浏览器上传图片到服务器(php),今天将这个功能付诸实践.(还完善了服务端的代码)

不试不知道,原来通过android 向服务端发送图片还真是挺麻烦的一件事.

上传代码:

/* 上传文件至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成功
            System.out.println(b.toString());
        } catch (Exception e)
        {
            /* 显示异常信息 */
//            Toast.makeText(MainActivity.this, "Fail:" + e, Toast.LENGTH_SHORT).show();//Post失败
            System.out.println(e);
        }
    }

上篇博文有说上传图片必须使用POST方法,这里当然使用的就是post方法.这里上传跟普通上传写法没啥变化.

不过我还是不习惯使用这个方法(我一直使用volley框架, 有兴趣可以百度一下.一个官方推出的很好用的框架,要不是需要用到传图我还不会研究这个写法)

使用原生POST方法的基本步骤:

  1.使用 HttpURLConnection 建立连接

  2.设置请求属性

  3.根据请求格式组装参数(很麻烦 , 可以通过浏览器发送POST请求,取出调试信息对比)

  4.建立输入流,并写入数据(FileInputStream 和下面循环写入哪里)

  5.获取返回流,并处理返回参数

  6.关闭所有流

该部分代码几乎完全借鉴大神的写法.里面注释也很多我也不多说了.

值得一提的是在4.0(android 版本)以后就已经不支持在主线程中执行上传,下载等耗时操作了.

这也很合理,假如你在上传文件的时候,突然你的网络不好,你就会一直在上传状态.体验很不好.

所以调用上面的方法需要新建一个线程:

 new Thread(new Runnable() {
                    @Override
                    public void run() {
                        uploadFile();
                    }
                }).start();

这个调用方法是在上传方法与该方法同文件时可以这样写,如果上传方法在独立的class文件中需要先实例化然后通过

实例化对象名.uploadFile();

的方法调用.

服务器端

  上篇博文里面只是简单的实现了,接收并转存图片.这里对该服务端进行完善:

<?php
/**
 * 接收上传的图片
 *
 * ------------
 * 200 ok
 * 401 Error method
 * 500 Internal error
 * ------------
 */
// ini_set("display_errors", "On");
// error_reporting(E_ALL | E_STRICT);
header(‘Access-Control-Allow-Origin: *‘);   // 解决前段javascript跨域请求

$fileInfo = $_FILES[‘file‘];
$maxSize=2097152;//允许的最大值

$allowExt=array(‘jpeg‘,‘jpg‘,‘png‘,‘gif‘,‘wbmp‘);
$flag=true;//检测是否为真实图片类型

if($fileInfo[‘error‘]==0){
    //判断上传文件的大小

    if($fileInfo[‘size‘]>$maxSize){
        $data = ‘上传文件过大‘;

        return Response::show(201,‘error1‘, $data);

        exit();
    }
    //$ext=strtolower(end(explode(‘.‘,$fileInfo[‘name‘])));获取后缀

    $ext=pathinfo($fileInfo[‘name‘],PATHINFO_EXTENSION);
    if(!in_array($ext,$allowExt)){

        $data = ‘非法文件类型‘;

        return Response::show(202 , ‘error2‘ , $data);

        exit();

    }
    //判断文件是否是通过HTTP POST方式上传来的

    if(!is_uploaded_file($fileInfo[‘tmp_name‘])){

        $data = ‘文件不是通过HTTP POST方式上传来的‘;

        return Response::show(203 , ‘error3‘ , $data);

        exit();
    }
    //检测是否为真实的图片类型

    if($flag){
        if(!getimagesize($fileInfo[‘tmp_name‘])){

        $data = ‘不是真正图片类型‘;

        return Response::show(204 , ‘error4‘ , $data);

        exit();

        }
    }

    //创建与id对应的文件夹 

    $id = $_GET[‘id‘];
    if(!file_exists($id)){
        mkdir(‘../files/‘.$id);
        //chmod($id , 0777);
    }

    if(@move_uploaded_file($fileInfo[‘tmp_name‘],‘../files/‘.$id.‘/‘.$fileInfo[‘name‘])){
        $data = ‘文件上传成功‘;

         return Response::show(200 , ‘ok‘ , $data);

    }else{
        $data = ‘文件上传失败‘;

         return Response::show(404 , ‘error5‘ , $data);
    }
}else{
    switch($fileinfo[‘error‘]){
        case 1:
            $data = ‘上传文件超过了PHP配置文件中upload_max_filesize选项的值‘;

            return Response::show(401 , ‘error5‘ , $data);

            break;

        case 2:

            $data = ‘超过了表单MAX_FILE_SIZE限制的大小‘;

            return Response::show(402 , ‘error5‘ , $data);

            break;
        case 3:

            $data = ‘文件部分被上传‘;

            return Response::show(403 , ‘error5‘ , $data);

            break;
        case 4:

            $data = ‘没有选择上传文件‘;

            return Response::show(405 , ‘error5‘ , $data);

            break;
        case 6:

            $data = ‘没有找到临时目录‘;

            return Response::show(405 , ‘error5‘ , $data);

            break;
        case 7:
        case 8:

            $data = ‘系统错误‘;

            return Response::show(405 , ‘error5‘ , $data);

            break;
    }
}

这里对图片进行了各种检测.比昨天的更可靠了是吧.还统一了返回的json格式方便客户端进行解析.(还有就是,上面的服务端的代码也是借鉴了慕课大神的写法,略作修改)

时间: 2024-10-24 08:30:43

通过android 客户端上传图片到服务器的相关文章

Android客户端与PC服务器通过socket进行交互实例(转)

一直以来对Android socket通信都很模糊,今天终于研究了一个网上的例子,自己又修改了下,算是对Android socket通信有点了解了. 下面是具体的代码,说明都在注释中了.需要注意的是,只有客户端发送了信息给服务器后,服务器才能响应客户端的输入,然后返回信息给客户端,这是客户端才能读取服务器返回的信息.如果客户端和服务器都处于等待对方的信息,那样就会造成阻塞,导致ANR了. 1.服务器端代码,就是一个java程序,与android无关,运行于服务器上,即PC机上. [java] v

Android客户端与本地服务器Socket通信

Android客户端与本地服务器Socket通信 Socket服务器运行结果图?? 一.客户端和服务器端的选择: 客户端是我们手机端,关于服务器端,只要安装了JDK,自然就拥有通讯的功能,我们只需要在Eclipse或者MyEclipse中写好文章中服务器端的代码,运行起来即可,用accept()方法启动服务器端,等待客户端的连接,在未连接的情况下,服务器端处于堵塞的状态. 二.客户端注意事项 andriod客户端添加网络访问权限 <uses-permission android:name="

Android客户端与云服务器进行网络通信

多写技术文档,多写技术文档,多写技术文档,重要的事情说三遍...... ------------------------------------------------------------------------------------------------------------------- 功能需求:Android客户端解析和显示云服务器返回的xml文件. 思路:涉及到Android端应用和Java ee端web应用的编码实现. 示例:Android客户端获取腾讯云服务器上的视频资讯

Android客户端与Java服务器交互数据(一)SAE服务器搭建

平时大家的测试服务器都是运行在自己的PC上面,用Tomcat或者IIS搭建的本机服务器.其实新浪云平台SinaAppEngine也是挺好用的.今天总结一下我使用过程中的一些小心得: 1.创建SAE应用: 登陆http://sae.sina.com.cn/进行注册,微博帐号可以直接登陆.注册成功后进入"我的首页",控制台>应用管理>创建新应用 然后输入二级域名(应用的唯一标示),应用名称和其他信息,最后选择开发语言,这里以Java为例: JVM级别选择"经济版&qu

Android客户端与Java服务器交互数据(二)阿里云ACE服务器搭建

前段时间写了一个新浪SAE部署代码的小总结,刚好今天阿里云云引擎ACE公测的审核资格通过了,就来对比一下ACE与新浪SAE的使用. 首先是账号,ACE作为阿里产品自然可以通过淘宝账号直接登录,而SAE则可以通过微博账号登录. http://www.aliyun.com/ 阿里云的主营业务比较多,主页很花哨,点击右上角的"管理控制台",然后进入"云引擎ACE",创建应用环境: 这里先写一个简单的JSP工程作为演示,打开Eclipse for JavaEE,然后File

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

SSH服务器与Android通信(3)--Android客户端发送数据

Android客户端向SSH服务器发送数据主要有三种情况:通过客户端删除数据.添加数据和修改数据. 1.删除数据 先看看jsp文件里面是怎样删除数据的: <td align="center"><a href="clasdelete.action?id=<s:property value='#st.id'/>" onclick="if(!window.confirm('是否删除'))return false;" >

android上传图片至服务器

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

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

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