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 of window) 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 like getTargetDirectory or something function of FileMixin.js and change the line let directory = cordova.file.dataDirectory to your let directory = cordova.file.applicationStorageDirectory + "files/Documents".


Log in to reply