1. 程式人生 > >拍照與圖片上傳,附全部原始碼!

拍照與圖片上傳,附全部原始碼!

感謝論壇高手們的帖子啟發,我在參考SimpleFileStore的基礎上,實現了使用者頭像照片的拍照、上傳與顯示,現分享如下:

1、拍照

呼叫手機拍照用的是cordova外掛,所以在你需要拍照的頁面中,首先要引用如下程式碼:

require("$UI/system/lib/cordova/cordova");

require("cordova!cordova-plugin-camera");

然後是呼叫相機拍照的函式,我是放在button的click事件中進行的:

Model.prototype.takePicBtnClick = function(event){

if(!navigator.camera){

return;

}

var self = this;

navigator.camera.getPicture(onLoadImageSuccess, onLoadImageFail, {

destinationType:navigator.camera.DestinationType.DATA_URL,

allowEdit:true,

quality:80,

targetWidth:100,

targetHeight:100,

saveToPhotoAlbum:true

});

//拍照成功後回撥

function onLoadImageSuccess(imageData){

localStorage.setItem("imageData","data:image/jpeg;base64,"+imageData);

var smallImage = document.getElementById(self.getIDByXID('image1'));

//顯示影象

smallImage.style.display = 'block';

smallImage.src = "data:image/jpeg;base64,"+imageData;

//圖片上傳

self.uploadPic(imageData);

}

function onLoadImageFail(error){

alert(error);

}

};

再然後是圖片的上傳:

//呼叫bass實現圖片上傳

Model.prototype.uploadPic = function(imageData){

//使用者資訊,用於上傳圖片後儲存圖片連結fImage

var userid = this._UserID; //this._UserID是自己定義的變數,在頁面開啟時被初始化

var userBaasData = this.comp("userBaasData");

var storeFileName = "";

var imageJson = {};

storeFileName = justep.UUID.createUUID();

justep.Baas.sendRequest({

"url" : "/summer/classes", //baas目錄,請根據自己的配置進行修改

"action" : "uploadPicfile",

"async" : false,

"params" : {

"picData" : imageData,

"ownerID" : userid,

"storeFileName" : storeFileName

},

"success" : function(data) {

justep.Util.hint("圖片上傳成功");

//修改資料庫中的圖片連結 這裡我的欄位名叫fImage,可以根據自己的欄位名修改

userBaasData.setFilter("Idfilter", "fID='"+userid+"'");

userBaasData.refreshData();

if(userBaasData.getCount()>0){

var fImage = '{"ownerID":"'+userid+'","storeFileName":"'+storeFileName+'"}';

userBaasData.setValue("fImage", fImage);

userBaasData.saveData();

}

}

});

};

然後是,後臺對應的圖片上傳baas,將圖片儲存在UI2/myClassmate/uploadfiles目錄下,這裡可以自己進行調整:

public static JSONObject uploadPicfile(JSONObject params, ActionContext context) throws SQLException, NamingException, IOException {

System.out.println("uploadPicfile is running...");

String ownerID = params.getString("ownerID");

String storeFileName = params.getString("storeFileName");

String picData = params.getString("picData");

String baasPath = Thread.currentThread().getContextClassLoader().getResource("").getPath() ;

String docStorePath = baasPath + ".." + File.separator + ".."+ File.separator + "model" +File.separator + "UI2" +File.separator + "myClassmate" +File.separator+"uploadfiles" ;

File docstoreDir = new File(docStorePath);

if(!(docstoreDir.exists() && docstoreDir.isDirectory())){

docstoreDir.mkdirs();

}

String storePath = docStorePath + File.separator + ownerID;

File storeDir = new File(storePath);

if(!(storeDir.exists() && storeDir.isDirectory())){

storeDir.mkdirs();

}

System.out.println("後臺計算的baasPath的值:"+ baasPath);

System.out.println("後臺計算的docStorePath的值:"+ docStorePath);

System.out.println("後臺計算的storeDir的值:"+ storeDir);

BASE64Decoder decoder = new BASE64Decoder();

try {

byte[] decodedBytes = decoder.decodeBuffer(picData);

String imgFile = storePath + File.separator + storeFileName;

FileOutputStream out = new FileOutputStream(imgFile);

out.write(decodedBytes);

out.close();

System.out.println("圖片上傳成功!");

} catch (Exception e) {

System.out.println("圖片上傳失敗!");

e.printStackTrace();

}

return null;

}

2 選擇照片

選擇照片只能從相簿中選,跟拍照比,只是在呼叫corvoda外掛是,一個引數不同。

//選擇照片

Model.prototype.selPicBtnClick = function(event){

if(!navigator.camera){

return;

}

var self = this;

navigator.camera.getPicture(onSuccess, onFail, {

mediaType : 0,//只選擇圖片

quality:80,

allowEdit:true,

targetWidth:100,

targetHeight:100,

destinationType: navigator.camera.DestinationType.DATA_URL, sourceType: navigator.camera.PictureSourceType.PHOTOLIBRARY

//sourceType: navigator.camera.PictureSourceType.PhotoAlbum//在安卓中,這個引數會跳出拍照介面

});

function onSuccess(imageData) {

var smallImage = document.getElementById(self.getIDByXID('image1'));

smallImage.style.display = 'block';

smallImage.src = "data:image/jpeg;base64,"+imageData;

//圖片上傳

self.uploadPic(imageData);

}

function onFail(message) {

alert('Failed because: ' + message);

}

};

3 照片顯示

頁面被重新整理時,照片要根據資料庫中的連結,顯示在圖片的位置,參考外賣的案例,我在資料庫中是這樣儲存fImage欄位的:

{"ownerID":"U01","storeFileName":"C708594A6EE00001F11723001E2011CF"}

記錄這張圖片的主人ownerID,和名字stroreFileName,主人用來作為儲存目錄,名字就是一個沒有後綴名的檔案。

要把這些資訊解析成後臺對應的檔案,就需要另外定義一個函式:

//顯示使用者頭像,自定義

Model.prototype.transUrl = function(fImage) {

if(!fImage)

return null;

this.actionUrl = "/baas/summer/classes/browsePicfile";

var src = null;

if (fImage !== null && fImage !== "" && fImage !== "[]") {

var imageJson = eval("("+fImage+")");

var storeFileName = imageJson.storeFileName;

var ownerID = imageJson.ownerID;

var url = this.actionUrl + '?storeFileName=' + storeFileName + '&ownerID=' + ownerID ;

src = require.toUrl(url);

}

return src;

};

定義該函式後,將想要顯示圖片的image空間的屬性 bind-attr-src 設為如下值:

$model.transUrl(userData.val('fImage'))

其中userData的欄位fImage就是存有{"ownerID":"U01","storeFileName":"C708594A6EE00001F11723001E2011CF"}這樣內容的欄位。

顯示圖片呼叫的對後臺baas如下:

//顯示圖片檔案

private static final int BUFFER_SIZE = 32768 * 8;

public static JSONObject browsePicfile(JSONObject params, ActionContext context) throws SQLException, NamingException, IOException {

System.out.println("browsePicfile is running...");

HttpServletRequest request = (HttpServletRequest)context.get(ActionContext.REQUEST);

HttpServletResponse response = (HttpServletResponse)context.get(ActionContext.RESPONSE);

String baasPath = Thread.currentThread().getContextClassLoader().getResource("").getPath() ;

String docStorePath = baasPath + ".." + File.separator + ".."+ File.separator + "model" +File.separator + "UI2" +File.separator + "myClassmate" +File.separator+"uploadfiles" ;

String ownerID = request.getParameter("ownerID");

String storeFileName = request.getParameter("storeFileName");

File file = new File(docStorePath + File.separator +ownerID + File.separator + storeFileName);

FileInputStream fis = new FileInputStream(file);

response.setHeader("Cache-Control", "pre-check=0, post-check=0, max-age=0");

String fileNameKey = "filename";

response.addHeader("Content-Disposition", "inline; "+fileNameKey+"=\"" + storeFileName + "\"");

OutputStream os = response.getOutputStream();

byte[] buffer = new byte[BUFFER_SIZE];

try {

int read;

while ((read = fis.read(buffer)) != -1) {

os.write(buffer, 0, read);

}

} finally {

fis.close();

}

return null;

}

OK!以上程式碼經過打包模式1,和打包模式3的測試,均可正常執行,歡迎大家改寫成自己的更強版本。