国内最全IT社区平台 联系我们 | 收藏本站
华晨云阿里云优惠2
您当前位置:首页 > php开源 > 综合技术 > [置顶] react native 图片上传,以及服务端( php )示例程序

[置顶] react native 图片上传,以及服务端( php )示例程序

来源:程序员人生   发布时间:2017-02-05 13:51:04 阅读次数:6105次

    • react native 编写界面
      • 界面样式
        • 设计图
        • 示例代码
    • react native 加载图片
      • 几点说明
      • 示例代码
    • react native 上传图片
      • 接口部份
      • 调用示例
    • 服务器端设计
      • 服务器配置
        • 安装Apache
        • 配置根目录
        • 配置上传目录的属性
        • 配置上传文件时的参数
      • 几个简单的API介绍
        • pathinfo
        • file_exists
        • getimagesize
        • move_uploaded_file
      • php 示例代码
    • 运行效果
      • 客户端上传图片
      • 服务端接收

react native 编写界面

界面样式

设计图:

这里写图片描述

示例代码

布局很简单,只罗列 关键部位的代码


_renderAddImageView(index){
    if (this.state.avatarSource!=null&&index<this.state.avatarSource.length) {
       return(
         <Image
           source={require('../../img/service/虚线框.png')}
           style ={addImageViewStyles.image}>
           <Image source={this.state.avatarSource[index]} style={addImageViewStyles.imageL} />
           <TouchableOpacity
             onPress ={this.deleteLoadedImage.bind(this,index)}
             style={addImageViewStyles.rightDelButton}>
             <Image source={require('../../img/service/删除.png')}/>
           </TouchableOpacity>
         </Image>
       );
    }
    if ((this.state.avatarSource==null||this.state.avatarSource.length<1)&&index==1){
        return null;
    }
    return (
      <Image
      source={require('../../img/service/虚线框.png')}
      style ={styles.image}>
      <TouchableOpacity onPress = {this.addOnClicked.bind(this)}>
        <Image source={require('../../img/service/添加.png')}></Image>
      </TouchableOpacity>
      <Text style ={styles.normalTitle}>上传图片</Text>
      <Text style ={styles.normalText}>(最多能上传2张)</Text>
      </Image>
    );
  }

react native 加载图片

几点说明

根据不同端访问相册的不同可分别处理 ,由于触及到原生和react native 的混合开发,相对复杂建议使用1个兼容iOS 和Android的第3方库来实现该功能。下面的示例使用的是react-native-image-picker 。

示例代码

ImagePicker.launchImageLibrary(options, (response)  => { 
      if (response.didCancel) {
        console.log('用户点击了取消');
      }
      else if (response.error) {
        console.log('ImagePicker 出错: ', response.error);
      }
      else { 
        let source = {uri: 'data:image/jpeg;base64,' + response.data, isStatic: true};  
        if (Platform.OS === 'ios') {
           source = {uri: response.uri.replace('file://', ''), isStatic: true};
        } else {
           source = {uri: response.uri, isStatic: true};
        }
        let imageArray = this.state.avatarSource;
        imageArray.push(source);
        let imgFileNameArray = this.state.imgFileName;
        if (response.fileName!=null) {
            imgFileNameArray.push(response.fileName);
        }
        this.setState({
          avatarSource:imageArray,
          imgFileName:imgFileNameArray
        });
      }
    });

react native 上传图片

接口部份

封装上传文件的接口

function fetchUploadAction(...props) {
  this.url = props.shift(1);
  this.options = props.shift(1); 
  return fetch(this.url, Object.assign({}, this.options))
  .then((response) => {
    const bodyBlob = response["_bodyBlob"];
    if (bodyBlob != null && bodyBlob.size == 0) {
       return null;
    }
    const headers = response["headers"]
    if (headers != null) {
      const mapHeader = headers["map"];
      if (mapHeader != null) {
        contentLength = mapHeader["content-length"];
        if (contentLength != null && contentLength == 0) {
          return null;
        }
      }
    }
    return response.json()
  });

调用上面的接口,专门用来上传图片

//imagesObject是存储调用相册返回的选中的图片的多个对象,可取得图片uri
//fileName 这几个对象对应的文件名,也可不要这个参数 从上面的uri中截取
function postUpLoadImage_Attachment(imagesObject,fileName) {
    var apiPort = "v1/cases/attachments/";
    let retObject = null;
    for(let i=0;imagesObject!=null&&i<imagesObject.length;i++){
      let formData = new FormData();
      let tmpUri =imagesObject[i];
      //DateFormatTool.GetDateTimeStrValue() 是获得当前时间的时间戳字符串
      let tmpfileName=DateFormatTool.GetDateTimeStrValue()+"_"+i+"_"+fileName[i];
      let file = {uri:tmpUri.uri,type:'multipart/form-data',name:tmpfileName};
      formData.append("attachment",file);
      retObject=fetchUploadAction(`${kParCRMAPIBaseURL}/${apiPort}`, {
        method: 'post',
        headers: {
            'Content-Type':'multipart/form-data',
         },
         body: formData,
      });
    }
    return retObject;
  },

调用示例

try {
          CRMServiceApiNet.postUpLoadImage_Attachment(this.state.avatarSource,this.state.imgFileName)
          .then((response) => {
            this.updateLoadingState(false);
            if(response!=null&&response.code) {
                HandleErrorManager.handleObj(response);
            } else {
                console.log("上传成功"+response);
                this.sendTheQuestionSuccess();
            }
          })
        } catch(e) {
          this.updateLoadingState(false);
          StandardAlertCom.show('提示','网络毛病',[
          {
            text: '肯定',
            onPress: () => console.log('肯定 Pressed!')
          }
        ]);
      }

服务器端设计

服务器配置

安装Apache ,配置服务器环境 , 设置最大的上传文件的大小和上传文件的并发个数 ,和要上传到的目录的属性必须为可写。。。下面是以mac 电脑为例,配置服务器相干属性。

安装Apache

这1步跳过 ,由于mac 上自带 Apache 环境 。

配置根目录

使用命令行工具 cd 到 /etc目录 如图
这里写图片描述

配置上传目录的属性

运行命令 ls *php* ,找到php.init 文件,如果没有 则找到 php.ini.default copy 1份,
注意将原文件copy 1份 ,以防修改出错

配置上传文件时的参数

file_uploads = on ;是不是允许通过HTTP上传文件的开关。默许为ON即是开

upload_max_filesize = 8m ; 即允许上传文件大小的最大值。默许为2M

post_max_size = 8m ;指通过表单POST给PHP的所能接收的最大值,包括表单里的所有值。默许为8M

1般地,设置好上述4个参数后,上传<=100M的文件是不成问题,在网络正常的情况下。
但如果要上传>8M的大体积文件,只设置上述4项还1定能行的通。还得设置以下参数:

max_execution_time = 600 ;每一个PHP页面运行的最大时间值(秒),默许30秒

max_input_time = 600 ;每一个PHP页面接收数据所需的最大时间,默许60秒

memory_limit = 8m ;每一个PHP页面所吃掉的最大内存,默许8M

如果上面配置后还不成功,你可以把php.ini.default 再配置1下。

几个简单的API介绍

1.pathinfo

函数原型: pathinfo(path,options)
定义和用法

pathinfo() 函数以数组或字符串的情势返回关于文件路径的信息。

返回的数组元素以下:

[dirname]: 返回文件路径中的目录部份
[basename]: 返回文件路径中文件名的部份
[extension]: 返回文件路径中文件的类型的部份

2.file_exists

定义和用法

file_exists() 函数检查文件或目录是不是存在。
如果指定的文件或目录存在则返回 true,否则返回 false。

语法

file_exists(path)

参数 描写

path 必须。规定要检查的路径。

3.getimagesize

getimagesize() 函数用于获得图象尺寸,类型等信息。
本函数可用来获得 GIF、JPEG 及 PNG 格式的图片的高与宽,(不需要安装 GD library 就能够使用本函数)

返回的数据解析(成功返回1个数组,失败则返回 FALSE )

返回的数组有4个元素。

返回数组的第1个元素 (索引值 0) 是图片的高度,单位是像素 (pixel)。

第2个元素 (索引值 1) 是图片的宽度。

第3个元素 (索引值 2) 是图片的文件格式,其值 1 为 GIF 格式、 2 为 JPEG/JPG 格式、3 为 PNG 格式。

第4个元素 (索引值 3) 为图片的高与宽字符串,height=xxx width=yyy。可省略的参数 imageinfo 用来获得1些图片的相干信息.

4.move_uploaded_file

函数原型 : move_uploaded_file(file ,newloc)

参数描写

file 必须。规定要移动的文件。
newloc 必须。规定文件的新位置。

说明

该函数检查并确保由 file 指定的文件是合法的上传文件(即通过 PHP 的 HTTP POST 上传机制所上传的)。如果文件合法,则将其移动为由 newloc 指定的文件。
如果 file 不是合法的上传文件,不会出现任何操作,move_uploaded_file() 将返回 false。
如果 file 是合法的上传文件,但出于某些缘由没法移动,不会出现任何操作,move_uploaded_file() 将返回 false,另外还会发出1条正告。
这类检查显得格外重要,如果上传的文件有可能会造成对用户或本系统的其他用户显示其内容的话。

#

php 示例代码

本代码设计1个文件上传管理类 ,定义1系列的操作。$this->retErrorDetail 为返回的毛病信息,如果没有出错该值则为 null 。如果上传成功则返回1个json 数据,(哪些文件上传成功,文件的参数,哪些失败,失败的缘由)。
下面是主要函数的示例代码:

   function handleUploadAndSave($formkey){ 
        $FilekeyValue_FormData =$formkey;
        $theFile = $_FILES[$FilekeyValue_FormData]["tmp_name"]; 
        //Post multipart
        if ($_FILES[$FilekeyValue_FormData]["error"] > 0){
            $this->retErrorDetail="Error: " . $_FILES[$FilekeyValue_FormData]["error"];
            $this->formatDetailError($this->retErrorDetail);
            return false;
        }else{
             //打印上传2进制文件信息
            foreach($_FILES[$FilekeyValue_FormData] as $key=>$value){
                $this->formatDetailSuccess($key."=>".$value. "\n");
            }
            //定义上传的文件 保存的路径
            $target_dir = "/Users/XXXX/myWebServer/uploads/".$this->caseId."/";           
            $target_file = $target_dir.basename($_FILES[$FilekeyValue_FormData]["name"]);

            $uploadOK = 1;
            $imageFileType = pathinfo($target_file,PATHINFO_EXTENSION);
            // 检查 上传的文件是不是为图片
            $check = getimagesize($theFile);
            if($check !== false) {
                $this->formatDetailSuccess("文件是1个 图片- " . $check["mime"] . "."); 
                $uploadOk = 1;
            } else {
                $this->retErrorDetail="文件不是图片.";
                $this->formatDetailError($this->retErrorDetail);
                $uploadOk = 0;
            } 
            // 检测要上传的文件是不是 已被上传(在该目录下是不是已存在该文件)
            if (file_exists($target_file)) {
                $this->retErrorDetail="抱歉, 该文件已存在.";
                $this->formatDetailError($this->retErrorDetail);
                $uploadOk = 0;
            }
            //检测要上传文件的大小 >1mb
            if ($_FILES[$FilekeyValue_FormData]["size"] > 1024*1024) {
                $this->retErrorDetail="抱歉, 您上传的文件太大了";
                $this->formatDetailError($this->retErrorDetail);
                $uploadOk = 0;
            }
            //检测后缀名称
            $imageFileType = strtolower($imageFileType);
            if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg"
            && $imageFileType != "gif" ) {
                $this->retErrorDetail= "抱歉, 仅支持 JPG, JPEG, PNG & GIF files";
                $this->formatDetailError($this->retErrorDetail);
                $uploadOk = 0;
            }
            //检测是不是上传成功
            if ($uploadOk == 0) {
                $this->retErrorDetail="抱歉, 您的文件没有被上传成功.";
                $this->formatDetailError($this->retErrorDetail);
            } else {
                if (!mkdir("uploads")){
                    $this->formatDetailSuccess("创建目录失败");
                    return false;
                }

                if (move_uploaded_file($theFile,$target_file)) 
                {
                    $this->formatDetailSuccess("文件已被上传成功.");
                } else {
                    $this->retErrorDetail="抱歉, 保存文件时出现未知毛病.";
                    $this->formatDetailError($this->retErrorDetail);
                }
            }

        }
        if($uploadOk==0){
            return false;
        }
        return true;
    }

运行效果

客户端上传图片

这里写图片描述

服务端接收

在 uploads 目录下 ,找到创建的case 。(联系方式和具体的描写写在 文档里)
这里写图片描述

生活不易,码农辛苦
如果您觉得本网站对您的学习有所帮助,可以手机扫描二维码进行捐赠
程序员人生
------分隔线----------------------------
分享到:
------分隔线----------------------------
关闭
程序员人生