zoukankan      html  css  js  c++  java
  • 通过android 客户端上传图片到服务器

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

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

    上传代码:

    /* 上传文件至Server的方法 */
        private void uploadFile()
        {
            String end = "
    ";
            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格式方便客户端进行解析.(还有就是,上面的服务端的代码也是借鉴了慕课大神的写法,略作修改)

  • 相关阅读:
    1093 Count PAT's(25 分)
    1089 Insert or Merge(25 分)
    1088 Rational Arithmetic(20 分)
    1081 Rational Sum(20 分)
    1069 The Black Hole of Numbers(20 分)
    1059 Prime Factors(25 分)
    1050 String Subtraction (20)
    根据生日计算员工年龄
    动态获取当前日期和时间
    对计数结果进行4舍5入
  • 原文地址:https://www.cnblogs.com/wobeinianqing/p/5484035.html
Copyright © 2011-2022 走看看