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 的混合开发,相对复杂建议使用一个兼容iOS 和Android的第三方库来实现该功能。下面的示例使用的是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
这一步跳过 ,因为mac 上自带 Apache 环境 。
配置根目录
使用命令行工具 cd 到 /etc目录 如图
配置上传目录的属性
运行命令 ls *PHP* ,找到PHP.init 文件,如果没有 则找到 PHP.ini.default copy 一份,
注意将原文件copy 一份 ,以防修改出错
配置上传文件时的参数
file_uploads = on ;是否允许通过HTTP上传文件的开关。默认为ON即是开
一般地,设置好上述四个参数后,上传<=100M的文件是不成问题,在网络正常的情况下。
但如果要上传>8M的大体积文件,只设置上述四项还一定能行的通。还得设置以下参数:
max_execution_time = 600 ;每个PHP页面运行的最大时间值(秒),默认30秒
如果上面配置后还不成功,你可以把PHP.ini.default 再配置一下。
几个简单的API介绍
1.pathinfo
函数原型: pathinfo(path,options)
定义和用法
返回的数组元素如下:
[dirname]: 返回文件路径中的目录部分
[basename]: 返回文件路径中文件名的部分
[extension]: 返回文件路径中文件的类型的部分
2.file_exists
定义和用法
file_exists() 函数检查文件或目录是否存在。
如果指定的文件或目录存在则返回 true,否则返回 false。
语法
file_exists(path)
参数 描述
path 必需。规定要检查的路径。
3.getimagesize
getimagesize() 函数用于获取图像尺寸,类型等信息。
本函数可用来取得 GIF、JPEG 及 PNG 格式的图片的高与宽,(不需要安装 GD library 就可以使用本函数)
返回的数据解析(成功返回一个数组,失败则返回 FALSE )
返回的数组有四个元素。
返回数组的第一个元素 (索引值 0) 是图片的高度,单位是像素 (pixel)。
第二个元素 (索引值 1) 是图片的宽度。
第三个元素 (索引值 2) 是图片的文件格式,其值 1 为 GIF 格式、 2 为 JPEG/JPG 格式、3 为 PNG 格式。
第四个元素 (索引值 3) 为图片的高与宽字符串,height=xxx width=yyy。可省略的参数 imageinfo 用来取得一些图片的相关信息.
4.move_uploaded_file
函数原型 : move_uploaded_file(file,newloc)
参数描述
说明
该函数检查并确保由 file 指定的文件是合法的上传文件(即通过 PHP 的 HTTP POST 上传机制所上传的)。如果文件合法,则将其移动为由 newloc 指定的文件。
如果 file 不是合法的上传文件,不会出现任何操作,move_uploaded_file() 将返回 false。
如果 file 是合法的上传文件,但出于某些原因无法移动,不会出现任何操作,move_uploaded_file() 将返回 false,此外还会发出一条警告。
这种检查显得格外重要,如果上传的文件有可能会造成对用户或本系统的其他用户显示其内容的话。
#
PHP 示例代码
本代码设计一个文件上传管理类 ,定义一系列的操作。$this->retErrorDetail 为返回的错误信息,如果没有出错该值则为 null 。如果上传成功则返回一个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{
//打印上传二进制文件信息
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("文件是一个 图片- " . $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 。(联系方式和具体的描述写在 文档里)