zwwcn

Just another WordPress.com site

Monthly Archives: July 2015

Upload multiple images in Cordorva

Recently I implemented code for uploading multiple images in Cordova, I will make some notes here.

Cordova has a file upload plugin, which only support one image each time. To allow user upload multiple images in one request, we first tried use html canvas read the images data and then send it along the form data.

canvas = document.createElement('CanvasId');
ctx = canvas.getContext('2d');
img = new Image();
img.onload = ->
canvas.height = img.height
canvas.width = img.width
ctx.drawImage(image,0,0)
dataURL = canvas.toDataURL('image/jpeg')
items[i].dataUri = dataURL
canvas = null

Make sure you read the image as jpeg format, if you read it as PNG format the file size would be much bigger. Now we have the images data in items array and we could send multiple images in one request. The problem with this approach is the canvas toDataURL uses the base64 encoding which increase the size by around 30%.

We want to get the smallest file size and avoid unnecessary base64 converstions(client and server side), then FormData is introduced. We also use deferred to make sure all images are loaded before processing the form data.


saveChecklistImages = (photo)->
deferred = new $.Deferred();
imageDeferredArray.push(deferred);
window.resolveLocalFileSystemURI(photo.fileSource,(fileEntry) ->
fileEntry.file(file) ->
reader = new FileReader();
reader.onloadend = ((e) ->
BASE64_MARKER = ";base64,";
dataURI = e.target.result;
base64Index = dataURI.indexOf(BASE64_MARKER) + BASE64_MARKER.length;
base64 = dataURI.substring(base64Index);
raw = window.atob(base64);
rawLength = raw.length;
array = new Uint8Array(new ArrayBuffer(rawLength));
for i in [0..rawLength-1]
array[i] = raw.charCodeAt(i);
formData.append("attachment[]", new Blob([array],{type:'image/jpeg'}),photo.fileName)
}
reader.readAsDataURL(file);
)
)

saveData(URL,method,successMsg, errorMsg) ->
imageDeferredArray = [];
for photo in items
saveChecklistImages(photo)
$when.apply(null,imagedeferredArray).done(-> saveDataMain(URL,method,successMsg, errorMsg));

Now the page only read images data when user click save. Images data are added to FormData as Unit8Array, so we don’t need to do the base64 decoding at server side. It only send one request to post multiple images.