您的位置:首页 > 其它

PhoneGap 拍照并上传到远程服务器

2015-07-29 16:40 435 查看
本文主要介绍如何通过PhoneGap调用摄像头拍照,并且把拍照后的图片自动发送到服务器。

处理文件上传需要服务端的支持,为了简单,我直接用了PHP,如下面的代码所示:

<?php
if ($_FILES["file"]["error"] > 0){
echo "Return Code: " . $_FILES["file"]["error"] . "<br />";
}else{
echo "Upload: " . $_FILES["file"]["name"] . "<br />";
echo "Type: " . $_FILES["file"]["type"] . "<br />";
echo "Size: " . ($_FILES["file"]["size"] / 1024) . " Kb<br />";
echo "Temp file: " . $_FILES["file"]["tmp_name"] . "<br />";

if (file_exists("upload/" . $_FILES["file"]["name"])){
echo $_FILES["file"]["name"] . " already exists. ";
}else{
move_uploaded_file($_FILES["file"]["tmp_name"], "upload/" . $_FILES["file"]["name"]);
echo "Stored in: " . "upload/" . $_FILES["file"]["name"];
}
}
?>


代码很简单,其核心其实就是一句话:move_uploaded_file($_FILES["file"]["tmp_name"], "upload/" . $_FILES["file"]["name"]) ,表示将name为"file"的文件保存到服务器的upload文件夹下。

我们可以自己写一段HTML代码测试服务端是否可用。如下所示:

<!doctype html>
<html>
<body>
<form action="upload_file.php" method="post"
enctype="multipart/form-data">
<label for="file">Filename:</label>
<input type="file" name="file" id="file" />
<br />
<input type="submit" name="submit" value="Submit" />
</form>

</body>
</html>


通过浏览器访问然后提交,就可以看到如下效果:

Upload: appmobi_iphone.js
Type: application/x-javascript
Size: 6.912109375 Kb
Temp file: C:\Windows\temp\php60ED.tmp
Stored in: upload/appmobi_iphone.js


服务端OK后,我们开始编写PhoneGap代码,首先看HTML代码,非常简单,只定义一个按钮,然后引入一些脚本。如下所示:

<!DOCTYPE html>
<html>
<head>
<title>PhoneGap Upload</title>
<meta http-equiv="Content-Type" content="text/html; charset=UTF-8" />
<meta name="viewport" content="width=device-width, initial-scale=1, maximum-scale=1, user-scalable=0"/>
<meta name="apple-mobile-web-app-capable" content="yes" />
<meta name="apple-mobile-web-app-status-bar-style" content="black-translucent" />
<meta name="format-detection" content="telephone=no" />
<style>

.button-block {
margin-bottom: 0;
box-shadow: inset 0 1px 1px rgba(255, 255, 255, .4), 0 1px rgba(255, 255, 255, .8);
display: block;
padding: 11px 0 13px;
margin-bottom: 10px;
font-size: 16px;

}

.button-main{
color: #fff;
text-shadow: 0 -1px 0 rgba(0, 0, 0, .3);
background-color: #1eafe7;
background-image: -webkit-linear-gradient(top, #1eafe7 0, #1a97c8 100%);
background-image: linear-gradient(to bottom, #1eafe7 0, #1a97c8 100%);
border: 1px solid #117aaa;
font-weight: bold;
line-height: 18px;
text-align: center;
vertical-align: top;
cursor: pointer;
border-radius: 3px;
box-shadow: inset 0 1px 1px rgba(255, 255, 255, .4), 0 1px 2px rgba(0, 0, 0, .05);
-webkit-transition: background .3s linear;

}

</style>
</head>
<body>
<div class="button-block button-main" id='upload'>拍照上传</div>
<script  src="js/cordova-2.6.0.js"></script>
<script  src="js/zepto.min.js"></script>
<script  src="js/when.js"></script>
<script  src="js/upload_pic.js"></script>
</body>
</html>


按钮用CSS3来控制,同时引入PhoneGap的脚本和zepto.js(兼容jQuery接口,但是更为小巧,针对移动端优化)。由于PhoneGap调用本地设备都是异步的,需要开发人员提供回调。为了以同步的方式编写异步代码,我们引入了when.js,

upload_pic.js是我们的业务代码。如下所示:

(function() {
// 事件绑定
$("#upload").bind("click",function() {
takePicture().then(uploadPicture).then(deletePictureFromCache);
});

// 打卡摄像头拍照
function takePicture() {
var deferred  = when.defer(),
destinationType=navigator.camera.DestinationType,
options = {
quality: 100,
destinationType: destinationType.FILE_URI
//sourceType: Camera.PictureSourceType.PHOTOLIBRARY,
//cameraDirection: Camera.Direction.FRONT,
//targetWidth: 240,
//targetHeight: 320,
//correctOrientation: true
};

navigator.camera.getPicture(function(data){
deferred.resolve(data);
}, null, options);

return deferred.promise
}

// 上传图片到服务器
function uploadPicture( imageURI ){
var deferred  = when.defer(),
options = new FileUploadOptions();
options.fileKey = "file",
options.fileName = imageURI.substr(imageURI.lastIndexOf('/')+1);
options.mimeType = "image/jpeg";

var ft = new FileTransfer();
// 上传回调
ft.onprogress = showUploadingProgress;
navigator.notification.progressStart("", "当前上传进度");
ft.upload( imageURI, encodeURI('http://10.4.45.90/upload/upload_file.php'), function(){
deferred.resolve( imageURI );
navigator.notification.progressStop();
} , null, options);
return deferred.promise
}

// 显示上传进度
function showUploadingProgress( progressEvt ){
if( progressEvt.lengthComputable ){
navigator.notification.progressValue( Math.round( ( progressEvt.loaded / progressEvt.total ) * 100) );
}
}

// 从缓存中删除图片
function deletePictureFromCache( imageURI ){
window.resolveLocalFileSystemURI(fileURI, function( fileEntry ){
fileEntry.remove();
}, null);
}

})();


分析我们的业务,我们的业务流程是:1、打开摄像头拍照; 2、上传文件到服务器; 3、如果照片不再使用,需要将照片从缓存中删除。

3个流程,后一个必须依赖前一个,也就是所只有拍照成功了,才能上传到服务器,图片才能删除。由于每一个都是异步的,所以直接编写代码会显得很乱,这就是为什么要引入when.js的原因。由于异步编程涉及到不少知识,

各位可以猛击下这篇文章:基于事件的
JavaScript 编程:异步与同步。

再说下如何实现拍照、上传并显示进度以及从缓存中删除图片。

拍照很简单,直接调用navigator.camera.getPicture即可,可以设置返回的格式,如URI或者base64加密的数据,官方推荐用前者,因为后者在某些Android手机会出现一些内存问题。

上传文件主要调用 FileTransfer对象,它有一个upload方法,可以向指定的服务器POST数据,并可以在onProgress事件中捕获到上传文件。这个和HTML5中的XMLHttpRequest Level2标准中onprogress事件一致。

显示上传进度,我们直接调用了 navigator.notification.progressStart、navigator.notification.progressValue、navigator.notification.progressStop等方法,这几个方法在PhoneGap API中好像没提到,我是自己翻看源码才

发现的 :-)

最后是删除缓存中文件,PhoneGap拍照时,会把文件保存在SD卡中的/Android/data/com.flyingzl/cache目录下,其中com.flyingzl是我们程序的packageName。可以见Cordova中的源码:

protected static String getTempDirectoryPath(Context ctx) {
File cache = null;

// SD Card Mounted
if (Environment.getExternalStorageState().equals(Environment.MEDIA_MOUNTED)) {
cache = new File(Environment.getExternalStorageDirectory().getAbsolutePath() +
"/Android/data/" + ctx.getPackageName() + "/cache/");
}
// Use internal storage
else {
cache = ctx.getCacheDir();
}

// Create the cache directory if it doesn't exist
if (!cache.exists()) {
cache.mkdirs();
}

return cache.getAbsolutePath();
}


PhoneGap也提供了获取文件和删除文件的接口,即 window.resolveLocalFileSystemURI。这个方法是异步的,其回调得到的就是FileEntry对象,这样就可以删除文件。最后,我们看看效果(样例代码点击下载

内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: