Store picture from camera to device
-
I try to store a picture taken by camera to a specific folder on the device. Despite a lot of examples on the web I am not able to get the code working.
I try this on the device - so via “quasar build” and afterwards “cordova run android” and not via dev mode.
Got someone a hint for me what I overlook?
data() { return { imageSrc: "", fileStorageDirectory: "" }; }, methods: { takePhoto() { navigator.camera.getPicture( data => { this.moveFile(data); }, () => { // on fail this.$q.notify("Could not access device camera."); }, { // Options quality: 50, destinationType: navigator.camera.DestinationType.FILE_URI, encodingType: navigator.camera.EncodingType.JPEG, MEDIATYPE: navigator.camera.MediaType.PICTURE, sourceType: navigator.camera.PictureSourceType.CAMERA, mediaType: navigator.camera.MediaType.PICTURE, cameraDirection: navigator.camera.Direction.BACK, correctOrientation: false, allowEdit: false } ); }, moveFile(fileURI) { window.resolveLocalFileSystemURL( fileURI, function(fileEntry) { window.resolveLocalFileSystemURL( this.fileStorageDirectory, function(dirEntry) { fileEntry.moveTo( dirEntry, fileEntry.name, onSuccess(fileEntry, dirEntry), onFail ); }, onFail ); }, onFail ); } }, mounted() { this.fileStorageDirectory = cordova.file.applicationStorageDirectory + "files/Documents"; }
-
@dirkhd not sure what’s wrong in your setup (maybe your use of
navigator
instead ofwindow
) but this works for me, i transformed most of the code from the docs (cam capture, creating, reading, moving, renaming, deleting, getting files and etc…) into promises and some async/awaits to ease out some of the callback hell.FileMixin.js
import { log, randomStr, base64toBlob } from 'assets/utils/app-utils' export default { methods: { getFileEntry (fileURL) { log('FILE GETFILE:::', fileURL) return new Promise((resolve, reject) => { window.resolveLocalFileSystemURL( fileURL, fileEntry => { log('FILE ENTRY', fileEntry) resolve(fileEntry) }, err => { reject(err) } ) }) }, readBinaryFile (fileEntry) { log('FILE READBINFILE:::', fileEntry) return new Promise((resolve, reject) => { fileEntry.file( file => { let reader = new FileReader() reader.readAsArrayBuffer(file) reader.onload = () => resolve(reader.result) reader.onerror = error => reject(error) }, err => { reject(err) } ) }) }, async moveCapturedImage (fileUri) { log('MOVE TO DATA::: ', fileUri) try { const fileEntry = await this.getFileEntry(fileUri) log('MOVE TO', fileEntry) let oldFileUri = fileUri let fileExt = '.' + oldFileUri.split('.').pop() let newFileName = Date.now() + randomStr() + fileExt const dirEntry = await this.getPersistentDirectory().then(res => res) // move the file to a new directory and rename it const moveParams = { oldFileUri, fileExt, newFileName, fileEntry, dirEntry } const finalResult = await this.moveFileTo(moveParams) log('FINAL RESULT:::', finalResult) return finalResult } catch (e) { throw e } }, moveFileTo ({ newFileName, fileEntry, dirEntry }) { return new Promise((resolve, reject) => { fileEntry.moveTo( dirEntry, newFileName, res => { log('SUCCESS MOVING::', res.toInternalURL()) resolve(res.toInternalURL()) }, err => { log('ERROR MOVING:::', err) reject(err) } ) }) }, getPersistentDirectory () { let directory = cordova.file.dataDirectory return new Promise((resolve, reject) => { window.resolveLocalFileSystemURL( directory, dirEntry => { log('FILE GETPERMDIR:::', dirEntry) resolve(dirEntry) }, e => { reject('FILE NOT FOUND', e) } ) }) }, async deleteImage (fileURL) { try { log('DELETE IMAGE:::', fileURL) const fileEntry = await this.getFileEntry(fileURL) const deleteResult = await this.deleteFile(fileEntry) log('DELETE RESULT:::', deleteResult) return deleteResult } catch (e) { throw e } }, deleteFile (fileEntry) { return new Promise((resolve, reject) => { fileEntry.remove( file => { log(`DELETE IMAGE::: FILE REMOVED ${file}`) resolve(file) }, error => { log(`ERROR FILE: `, error.code) reject(`Error deleting file:: ERR ${error.code}`) }, () => { reject('File does not exist') } ) }) }, writeFile (fileEntry, dataObj) { return new Promise((resolve, reject) => { fileEntry.createWriter( fileWriter => { fileWriter.onwriteend = () => { log(this.LOG_PREF + 'Successful file write...') resolve() } fileWriter.onerror = e => { log(this.LOG_PREF + 'Failed file write: ', e) reject(e) } // If data object is not passed in, // create a new Blob instead. // if (!dataObj) { // log(this.LOG_PREF + 'Creating blob.') // dataObj = new Blob(['missing data'], { type: 'text/plain' }) // } fileWriter.write(dataObj) }, err => { reject(err) } ) }) }, async createImageFileFromBase64 (fileName, data) { try { const dirEntry = await this.getPersistentDirectory() const fileEntry = await this.createFile(dirEntry, fileName) let block = data.split(';') // Get the content type of the image let contentType = block[0].split(':')[1] // In this case "image/gif" // get the real base64 content of the file let realData = block[1].split(',')[1] // In this case log( this.LOG_PREF + 'base64 stripped=>', contentType, '::::data::::', realData ) // let blob = this.base64toBlob(realData, contentType) let blob = base64toBlob(realData, contentType) await this.writeFile(fileEntry, blob) log('FILE CREATED B64IMAGE::', fileEntry.toInternalURL()) return fileEntry.toInternalURL() } catch (e) { throw e } }, createFile (dirEntry, fileName) { return new Promise((resolve, reject) => { dirEntry.getFile( fileName, { create: true, exclusive: false }, fileEntry => { resolve(fileEntry) }, err => { reject(err) } ) }) }, async getImageFile (fileURL) { try { const fileEntry = await this.getFileEntry(fileURL) const file = await this.readBinaryFile(fileEntry) log('GET IMAGE FILE:::', file) return { imgPath: fileEntry.nativeURL, imgFile: file } } catch (e) { throw e } } } }
CameraMixin.js
import FileMixin from '../file/FileMixin.js' export default { mixins: [FileMixin], methods: { async takePicture () { try { const imageURI = await this.getPicture() this.$appUtils.log('CAMERA:: img directory =>', imageURI) const moveResult = await this.moveCapturedImage(imageURI) this.$appUtils.log('CAMERA MOVERESULT::', moveResult) return moveResult } catch (e) { throw e } }, getPicture () { this.$appUtils.log('CAMERA GET PICTURE::') return new Promise((resolve, reject) => { navigator.camera.getPicture( imageURI => { resolve(imageURI) }, err => { reject(err) }, { // quality: 50, // destinationType: window.Camera.DestinationType.FILE_URI, // // destinationType: window.Camera.DestinationType.DATA_URL, // sourceType: window.Camera.PictureSourceType.CAMERA, // // encodingType: window.Camera.EncodingType.JPEG, // cameraDirection: 1, // saveToPhotoAlbum: true, // correctOrientation: true, quality: 100, // destinationType: window.Camera.DestinationType.NATIVE_URI, destinationType: window.Camera.DestinationType.FILE_URI, sourceType: window.Camera.PictureSourceType.CAMERA, encodingType: window.Camera.EncodingType.JPEG, // cameraDirection: window.Camera.Direction.BACK, cameraDirection: 0, correctOrientation: true, targetWidth: 500, targetHeight: 1000 // saveToPhotoAlbum: true } ) }) } } }
try changing the
getPersistentDirectory
or making your own likegetTargetDirectory
or something function of FileMixin.js and change the linelet directory = cordova.file.dataDirectory
to yourlet directory = cordova.file.applicationStorageDirectory + "files/Documents"
.