Image upload on APP not working... it works testing the app on localhost... chrome navigator. ¿app permissions needed to upload in app?

Hello
I’ve navigate to all the forum and documentation and i’ve find the way of uploading an image file to the php server using localhost, but not in the compiled app.
Running the “npm run serve” it’s works propertly on localhost
But I compile the app with “npm run build-cordova-android” and install it in my phone android device and the file transfer doesn’t work…

I don’t know if i need any permissions to pick a file to upload it through the app.
Anyway i can’t manage yet the pemissions.
I’ve try to install the NeoLSN/cordova-plugin-android-permissions,
with: cordova plugin add cordova-plugin-android-permissions
-> this solved here: How to add cordova plugin with F7
but when i execute this in cmd, inside my application folder it send me the text:
Current working directory is not a Cordova-based project.
I’ve made the proyect with:
framework7 create
and selected Cordova app
so i have compile it with
npm run build-cordova-android

Every other request i’ve made in the app works propertly but not the file one. I’ve try 2 different codes and both working in localhost.

Maybe this is not a permission question…
I can paste here the code…

<template>
<div class="page" data-name="form">
  <div class="navbar">
    <div class="navbar-bg"></div>
    <div class="navbar-inner sliding">
      <div class="left">
        <a href="#" class="link back">
          <i class="icon icon-back"></i>
          <span class="if-not-md">Back</span>
        </a>
      </div>
      <div class="title">Form</div>
    </div>
  </div>
  <div class="page-content">
    <div class="block-title">Subir foto test</div>
    <form>
    <div class="list no-hairlines-md">
      <ul>
        <li>
          <div class="item-content item-input">
            <div class="item-inner">
              <div class="item-title item-label">Subir foto</div>
              <div class="item-input-wrap">
                <input type="file" name="fileToUpload" id="fileToUpload">
              </div>
            </div>
          </div>
        </li>
        <li>
          <a href="#" class="col button button-round button-fill" @click="signIn">Upload image</a></li>
        <li>
      </ul>
    </div>
  </form>
  </div>
</div>
</template>
<script>
  return {
    methods: {
      signIn: function () {

        var $ = this.$;
        var self = this;
        var app = this.$app;
        var router = this.$router;


        var varfileToUpload=document.getElementById('fileToUpload').files[0];
        var FData = new FormData();

        FData.append('fileToUpload',varfileToUpload);    // this is main row

          var achus = app.request({
          url: 'http://url/upload_img.php', 
          method: 'POST', 
          data: FData,
          cache: false, 
          dataType: 'application/json',
          crossDomain: true, 
          contentType: 'multipart/form-data',
          processData: true, 
          success: function (data){
            //console.log(data);
            }
          });

          console.log(achus);
        achus.onload = function (e) {
          if (achus.readyState === 4) {
            if (achus.status === 200) {
              app.dialog.alert(" 1-Response Text: " + achus.responseText + " 1-Status Text: " + achus.statusText, function () {
                app.loginScreen.close();
                router.back();
              })
              //console.log(achus.responseText);
            } else {
              app.dialog.alert(" 2-Response Text: " + achus.responseText + " 2-Status Text: " + achus.statusText, function () {
                app.loginScreen.close();
                router.back();
              })
              //console.error(achus.statusText);
            }
          }
        };
        achus.onerror = function (e) {
          app.dialog.alert("Error name: " + e.name + " 3-Response Text: " + achus.responseText + " 3-Status Text: " + achus.statusText, function () {
            app.loginScreen.close();
            router.back();
          })
          //console.error(achus.statusText);
        };

      }
    }
  }
</script>

This works propertly on localhost:8080 but not in the android phone with compiled APP…
In the APP it shows the alert 3 with undefined in e.name and “” in both responseText and statusText when i select a file and press the uploading buttom.

Here the PHP:

<?php
header('Access-Control-Allow-Origin: *');

$target_dir = "uploads/";

$target_file = $target_dir . basename($_FILES["fileToUpload"]["name"]);
$uploadOk = 1;
$imageFileType = strtolower(pathinfo($target_file,PATHINFO_EXTENSION));
// Check if image file is a actual image or fake image
if(isset($_POST["submit"])) {
    $check = getimagesize($_FILES["fileToUpload"]["tmp_name"]);
    if($check !== false) {
        echo "File is an image - " . $check["mime"] . ".";
        $uploadOk = 1;
    } else {
        echo "File is not an image.";
        $uploadOk = 0;
    }
}
// Check if file already exists
if (file_exists($target_file)) {
    echo "Sorry, file already exists: " . $target_file;
    $uploadOk = 0;
}
// Check file size
if ($_FILES["fileToUpload"]["size"] > 500000) {
    echo "Sorry, your file is too large.";
    $uploadOk = 0;
}
// Allow certain file formats
if($imageFileType != "jpg" && $imageFileType != "png" && $imageFileType != "jpeg"
&& $imageFileType != "gif" ) {
    echo "Sorry, only JPG, JPEG, PNG & GIF files are allowed: " . $imageFileType;
    $uploadOk = 0;
}
// Check if $uploadOk is set to 0 by an error
if ($uploadOk == 0) {
    echo "Sorry, your file was not uploaded.";
// if everything is ok, try to upload file
} else {
    if (move_uploaded_file($_FILES["fileToUpload"]["tmp_name"], $target_file)) {
        echo "The file ". basename( $_FILES["fileToUpload"]["name"]). " has been uploaded.";
    } else {
        echo "Sorry, there was an error uploading your file.";
    }
}
?>

I’ve a simple code for the image upload working too in localhost but not in the app:

<template>
<div class="page" data-name="form">
  <div class="navbar">
    <div class="navbar-bg"></div>
    <div class="navbar-inner sliding">
      <div class="left">
        <a href="#" class="link back">
          <i class="icon icon-back"></i>
          <span class="if-not-md">Back</span>
        </a>
      </div>
      <div class="title">Form</div>
    </div>
  </div>
  <div class="page-content">
    <div class="block-title">Subir foto test</div>
    <form>
    <div class="list no-hairlines-md">
      <ul>
        <li>
          <div class="item-content item-input">
            <div class="item-inner">
              <div class="item-title item-label">Id</div>
              <div class="item-input-wrap">
                <input type="text" id="id" placeholder="Una id"/>
              </div>
            </div>
          </div>
        </li>
        <li>
          <div class="item-content item-input">
            <div class="item-inner">
              <div class="item-title item-label">Subir foto</div>
              <div class="item-input-wrap">
                <input type="file" name="fileToUpload" id="fileToUpload">
              </div>
            </div>
          </div>
        </li>
        <li>
          <a href="#" class="col button button-round button-fill" @click="signIn">Upload image</a></li>
        <li>
      </ul>
    </div>
  </form>
  </div>
</div>
</template>
<script>
  return {
    methods: {
      signIn: function () {
        var $ = this.$;
        var self = this;
        var app = this.$app;
        var router = this.$router;

  var f=document.getElementById('fileToUpload').files[0];   /// form input type="file"
  var id=document.getElementById('id').value;        /// form input type="number"
  var FData = new FormData();
  FData.append('fileToUpload',f);    /// for file object (on server in $_FILES['files'])
  FData.append('id',id);      /// for other data (on server in $_POST['id'])
    var achus = app.request.post('http://url/prb_login/upload_img.php', FData, function (data) {
      //console.log(data);
    });

        console.log(achus);
        achus.onload = function (e) {
          if (achus.readyState === 4) {
            if (achus.status === 200) {
              app.dialog.alert(" 1-Response Text: " + achus.responseText + " 1-Status Text: " + achus.statusText, function () {
                app.loginScreen.close();
                router.back();
              })
              //console.log(achus.responseText);
            } else {
              app.dialog.alert(" 2-Response Text: " + achus.responseText + " 2-Status Text: " + achus.statusText, function () {
                app.loginScreen.close();
                router.back();
              })
              //console.error(achus.statusText);
            }
          }
        };
        achus.onerror = function (e) {
          app.dialog.alert("Error name: " + e.name + " 3-Response Text: " + achus.responseText + " 3-Status Text: " + achus.statusText, function () {
            app.loginScreen.close();
            router.back();
          })
          //console.error(achus.statusText);
        };

      }
    }
  }
</script>

Both code examples working on localhost and upload the imagefile propertly.

This last code don’t opent any dialog.alert… in the app: do nothing when butom to upload the image is pressed
(i do nothing with the id parameter in the PHP, it’s for testing only how to pass another parameter)
The PHP code is the same for both code examples.

After managing how to upload the image i’ll store the image path and some other user values and so in the database; i now know how to do that… but first i need to solve uploading…

Thanks in advance

**NOTE: I’ve been searching… Maybe i need cordova plugin file transfer??? :confused:
How can I install a new cordova plugin in framework7?? -> this solved here: How to add cordova plugin with F7
:exploding_head:
:thinking: :sweat_smile:

I’ve managed to install filetransfer plugin and permissions one
with
framework7 cordova plugin add cordova-plugin-file
framework7 cordova plugin add cordova-plugin-file-transfer
framework7 cordova plugin add cordova-plugin-android-permissions

I’ve seen filetransfer is deprecated. So i need to learn the other way…
https://cordova.apache.org/blog/2017/10/18/from-filetransfer-to-xhr2.html

I’ve managed to upload a file (with deprecated filetransfer :upside_down_face:, i’ve seen it’s deprecated after coding) but only when i know the URL… the problem is the input type file can’t give the URL…

I’ve seen is needed to have READ_EXTERNAL_STORAGE permission to upload,
when you don’t have, can’t read the file…

I’ve does something like this:
This ask for the permission first but i’ve the same problem ever… while waiting for permission request the code continues and the app try to upload the file before the response… :man_facepalming:

The code now:

<template>
<div class="page" data-name="form">
  <div class="navbar">
    <div class="navbar-bg"></div>
    <div class="navbar-inner sliding">
      <div class="left">
        <a href="#" class="link back">
          <i class="icon icon-back"></i>
          <span class="if-not-md">Back</span>
        </a>
      </div>
      <div class="title">Form</div>
    </div>
  </div>
  <div class="page-content">
    <div class="block-title">Subir foto test</div>
    <form>
    <div class="list no-hairlines-md">
      <ul>
        <li>
          <div class="item-content item-input">
            <div class="item-inner">
              <div class="item-title item-label">Id</div>
              <div class="item-input-wrap">
                <input type="text" id="id" placeholder="Una id"/>
              </div>
            </div>
          </div>
        </li>
        <li>
          <div class="item-content item-input">
            <div class="item-inner">
              <div class="item-title item-label">Subir foto</div>
              <div class="item-input-wrap">
                <input type="file" name="fileToUpload" id="fileToUpload">
              </div>
            </div>
          </div>
        </li>
        <li>
          <a href="#" class="col button button-round button-fill" @click="signIn">Upload Image</a></li>
        <li>
      </ul>
    </div>
  </form>
  </div>
</div>
</template>
<script>
  return {
    methods: {
      signIn: function () {
        var $ = this.$;
        var self = this;
        var app = this.$app;
        var router = this.$router;



        var varfileToUpload=document.getElementById('fileToUpload').files[0];

        var permissions = cordova.plugins.permissions
        permissions.hasPermission(permissions.READ_EXTERNAL_STORAGE, function( status ){
          if ( status.hasPermission ) {
            console.log("Yes :D ");
          }
          else {
            permissions.requestPermission(permissions.READ_EXTERNAL_STORAGE, success, error);

            function error() {
              console.warn('READ_EXTERNAL_STORAGE Permission is not turned on');
            }

            function success( status ) {
              if( !status.hasPermission ) error();
            }

          }
        });


/*
        document.addEventListener("deviceready", onDeviceReady, false);
        function onDeviceReady() {
            console.log(FileTransfer);
        }
*/

        ///**** I can't get the URL in input type file ****
        var fileURL = "///storage/emulated/0/DCIM/prueba.jpg"

        var uri = encodeURI("http://URL/upload_img.php");
        var options = new FileUploadOptions();
        options.fileKey = "fileToUpload";
        options.fileName = fileURL.substr(fileURL.lastIndexOf('/')+1);
        options.mimeType = "image/jpeg";

        var headers = {'headerParam':'headerValue'};
        options.headers = headers;
        var ft = new FileTransfer();
        ft.upload(fileURL, uri, onSuccess, onError, options);

        function onSuccess(r) {
          app.dialog.alert(" Code: " + r.responseCode + " Response: " + r.response + " Sent: " +r.bytesSent, function () {
            app.loginScreen.close();
            router.back();
          })
          //console.log("Code = " + r.responseCode);
          //console.log("Response = " + r.response);
          //console.log("Sent = " + r.bytesSent);
        }

        function onError(error) {
          app.dialog.alert(" ERROR Code: " + error.code + " Upload Error Source: " + error.source + " Upload Error Target: " + error.target, function () {
            app.loginScreen.close();
            router.back();
          })
          //alert("An error has occurred: Code = " + error.code);
          //console.log("upload error source " + error.source);
          //console.log("upload error target " + error.target);
        }
      }
    }
  }
</script>

I’m in the way… I’m going to see what about xhr2: https://cordova.apache.org/blog/2017/10/18/from-filetransfer-to-xhr2.html

Thanks for help…

I assume you’re running the PHP on a remote server, ie the one you want to have the image uploaded to.

Did you check that you allowed your remote server to be reachable, in the Cordova Whitelist? https://cordova.apache.org/docs/en/latest/guide/appdev/whitelist/

I’ve made it… I’ve uploaded a file with the input file type through the android APP…
The problem now is the permission request … because of async i think… first time, when i made the request, the app try to upload the file before the response of the request, so the permission is not yet and the file uploading have error… second time it uploads because not need to ask for the permission anymore… but if client don’t give permission, it try to upload anyway… now i can’t continue, i need to rest…
i’ll continue tomorrow…
The CODE:

<template>
<div class="page" data-name="form">
  <div class="navbar">
    <div class="navbar-bg"></div>
    <div class="navbar-inner sliding">
      <div class="left">
        <a href="#" class="link back">
          <i class="icon icon-back"></i>
          <span class="if-not-md">Back</span>
        </a>
      </div>
      <div class="title">Form</div>
    </div>
  </div>
  <div class="page-content">
    <div class="block-title">Subir foto test</div>
    <form>
    <div class="list no-hairlines-md">
      <ul>
        <li>
          <div class="item-content item-input">
            <div class="item-inner">
              <div class="item-title item-label">Subir foto</div>
              <div class="item-input-wrap">
                <input type="file" name="fileToUpload" id="fileToUpload">
              </div>
            </div>
          </div>
        </li>
        <li>
          <a href="#" class="col button button-round button-fill" @click="signIn">Subir foto</a></li>
        <li>
      </ul>
    </div>
  </form>
  </div>
</div>
</template>
<script>
  return {
    methods: {
      signIn: function () {

        var $ = this.$;
        var self = this;
        var app = this.$app;
        var router = this.$router;

        //  PROBLEM TO SOLVE IN THE PERMISSION REQUEST
        var permissions = cordova.plugins.permissions
        permissions.hasPermission(permissions.READ_EXTERNAL_STORAGE, function( status ){
          if ( status.hasPermission ) {
            console.log("Yes :D ");
          }
          else {
            permissions.requestPermission(permissions.READ_EXTERNAL_STORAGE, success, error);

            function error() {
              console.warn('READ_EXTERNAL_STORAGE Permission is not turned on');
            }

            function success( status ) {
              if( !status.hasPermission ) error();
            }

          }
        });
       
        var varfileToUpload=document.getElementById('fileToUpload').files[0];

        var FData = new FormData();

        FData.append('fileToUpload',varfileToUpload);    // this is main row

          var achus = app.request({
          url: 'http://---URL---/upload_img.php', 
          method: 'POST', 
          data: FData,
          cache: false, 
          dataType: 'application/json',
          crossDomain: true, 
          contentType: 'multipart/form-data',
          processData: true, 
          success: function (data){
            //console.log(data);
            }
          });

          console.log(achus);
        achus.onload = function (e) {
          if (achus.readyState === 4) {
            if (achus.status === 200) {
              app.dialog.alert(" 1-Response Text: " + achus.responseText + " 1-Status Text: " + achus.statusText, function () {
                app.loginScreen.close();
                router.back();
              })
              //console.log(achus.responseText);
            } else {
              app.dialog.alert(" 2-Response Text: " + achus.responseText + " 2-Status Text: " + achus.statusText, function () {
                app.loginScreen.close();
                router.back();
              })
              //console.error(achus.statusText);
            }
          }
        };
        achus.onerror = function (e) {
          app.dialog.alert("Error name: " + e.name + " 3-Response Text: " + achus.responseText + " 3-Status Text: " + achus.statusText, function () {
            app.loginScreen.close();
            router.back();
          })
          //console.error(achus.statusText);
        };

      }
    }
  }
</script>

Thanks, i’will need this when i finish the app and compile it for production…
I had no idea about it !!! :sweat_smile: :sweat_smile: :sweat_smile:

Thanks!!!

I can see your other error: You are using http, not https.

Now i can upload witout giving any permission…
I deny the permission and the file uploads anyway…
Maybe the permisson is not needed and the pervious problem was other… i don’t know what…
but in the way i’ve learned a lot… :sweat_smile:

After that i’ve just remove the permission check, compile the app, upload it, and the uploading works…
I’ve see that app don’t have permission in android configuration…
:man_shrugging:

I don’t know why but i’ve taked the code posted first time, in the top message of this thread, and used it, and it’s working now in the compiled app
And when i posted it doesn’t work…
So it’s working without permission request, and nothing else that the same code who was maked me ask and become crazy about…
I don’t really know why now it works and not before… :man_shrugging: :man_shrugging: :man_shrugging: :man_shrugging: :man_shrugging: :man_shrugging: :exploding_head: :exploding_head:

How did you do yours?

var permissions = cordovaApp.plugins.permissions;

                      var list = [
                        permissions.ACCESS_COARSE_LOCATION,
                        permissions.ACCESS_FINE_LOCATION,
                        permissions.ACCESS_BACKGROUND_LOCATION,
                      ];

                      permissions.hasPermission(list, function( status ){
                        if ( status.hasPermission ) {
                          console.log("Yes :D ");
                        }
                        else {
                          console.warn("No :( ");

                          permissions.requestPermission(permissions.ACCESS_COARSE_LOCATION, success, error);

                          permissions.requestPermission(permissions.ACCESS_FINE_LOCATION, success, error);

                          permissions.requestPermission(permissions.ACCESS_BACKGROUND_LOCATION, success, error);
 
                          function error() {
                            console.warn('Location is not turned on');
                          }
                           
                          function success( status ) {
                            if( !status.hasPermission ) error();
                          }
                        }
                      });

I keep getting
0:9993 Uncaught (in promise) Error: TypeError: Cannot read property 'permissions' of undefined

I used something like this…

    var permissions = cordova.plugins.permissions
    permissions.hasPermission(permissions.WRITE_EXTERNAL_STORAGE, function( status ){
      if ( status.hasPermission ) {
        console.log("Yes :D ");
      }
      else {
        permissions.requestPermission(permissions.WRITE_EXTERNAL_STORAGE, success, error);

        function error() {
          console.warn('WRITE_EXTERNAL_STORAGE Permission is not turned on');
        }

        function success( status ) {
          if( !status.hasPermission ) error();
        }

      }
    });

I did that and still got error.

0:9993 Uncaught (in promise) Error: TypeError: Cannot read property ‘permissions’ of undefined

Maybe you don’t have installed the cordova plugin… You must have the plugin and try in the compiled apk