Ways to access file attributes and transfer a file in ionic 4?

I am facing an issue while attempting to transfer a file from my mobile device to Google bucket using Ionic 4. Although I can successfully upload the file, I am struggling to extract its properties from the file object.

Below is the method I am using:

async selectAFile() {

    const uploadFileDetails = {
      name: '',
      contentLength: '',
      size: '',
      type: '',
      path: '',
    };

    this.fileChooser.open().then(uri => {

      this.file.resolveLocalFilesystemUrl(uri).then(newUrl => {
        let dirPath = newUrl.nativeURL;

        const dirPathSegments = dirPath.split('/');
        dirPathSegments.pop();
        dirPath = dirPathSegments.join('/');

        window.resolveLocalFileSystemURL(
          newUrl.nativeURL,
          function(fileEntry) {
            uploadFileDetails.path = newUrl.nativeURL;

            const file: any = getFileFromFileEntry(fileEntry);

            //log 01 
            console.log({ file });

            uploadFileDetails.size = file.size;
            uploadFileDetails.name = `${newUrl.name
              .split(':')
              .pop()}.${file.type.split('/').pop()}`;
            uploadFileDetails.type = file.type;

            async function getFileFromFileEntry(fileEntry) {

              try {
                return await new Promise((resolve, reject) =>
                  fileEntry.file(resolve, reject)
                );
              } catch (err) {
                console.log(err);
              }
            }

          },
          function(e) {
            console.error(e);
          }
        );
      });
    });

    // here uploadFileDetails is similar to what I declared at the top ;)
    // I want this to be populated with file properties
    // console.log(uploadFileDetails.name) --> //''

    const uploadUrl = await this.getUploadUrl(uploadFileDetails);

    const response: any = this.uploadFile(
      uploadFileDetails,
      uploadUrl
    );

    response
      .then(function(success) {
        console.log({ success });
        this.presentToast('File uploaded successfully.');
        this.loadFiles();
      })
      .catch(function(error) {
        console.log({ error });
      });
  }

Although I can log the file in log 01, I encounter difficulties in retrieving file properties such as size, name, type from the resolveLocalFileSystemURL function. Essentially, I cannot populate the uploadFileDetails object. Can anyone provide guidance on what may be going wrong here? Thank you in advance.

Answer №1

in order to successfully upload a file and retrieve its metadata, you will need 4 essential Ionic and Cordova plugins.

  1. FileChooser

    This plugin facilitates opening the file picker on Android for selecting a file, returning a file URI.

  2. FilePath

    Allows resolution of native filesystem path for Android content URIs, built upon code from the aFileChooser library.

  3. File

    Implements a File API enabling read/write access to files on the device.

  4. File Transfer

    Enables file uploading and downloading functionality.

obtaining file metadata:

  • file.resolveLocalFilesystemUrl with fileEntry.file provides all necessary metadata except for the file name. The 'name' property in the metadata always displays 'content' as its value.
  • To retrieve the human-readable file name, filePath is needed. However, the returned file path cannot be used to fetch metadata; the original URL from fileChooser is required.
  • filePathUrl.substring(filePathUrl.lastIndexOf('/') + 1)
    isolates the file name from the filePath.
  • The 'nativeURL' of the file is crucial for successful uploads; utilizing the file path derived from filePath will not suffice.
    getFileInfo(): Promise<any> {
            return this.fileChooser.open().then(fileURI => {
                return this.filePath.resolveNativePath(fileURI).then(filePathUrl => {
                    return this.file
                        .resolveLocalFilesystemUrl(fileURI)
                        .then((fileEntry: any) => {
                            return new Promise((resolve, reject) => {
                                fileEntry.file(
                                    meta =>
                                        resolve({
                                            nativeURL: fileEntry.nativeURL,
                                            fileNameFromPath: filePathUrl.substring(filePathUrl.lastIndexOf('/') + 1),
                                            ...meta,
                                        }),
                                    error => reject(error)
                                );
                            });
                        });
                });
            });
        }

selecting a file from the mobile's file system:

async selectAFile() {

    this.getFileInfo()
        .then(async fileMeta => {

            //get the upload 
            const uploadUrl = await this.getUploadUrl(fileMeta);

            const response: Promise < any > = this.uploadFile(
                fileMeta,
                uploadUrl
            );

            response
                .then(function(success) {
                    //upload success message                       
                })
                .catch(function(error) {
                    //upload error message
                });
        })
        .catch(error => {
            //issue encountered while retrieving file information
        });
}

initiating the upload process:

The actual upload process depends on the backend setup. Here's how to utilize File Transfer plugin for file uploads.

uploadFile(fileMeta, uploadUrl) {

    const options: FileUploadOptions = {
      fileKey: 'file',
      fileName: fileMeta.fileNameFromPath,
      headers: {
        'Content-Length': fileMeta.size,
        'Content-Type': fileMeta.type,
      },
      httpMethod: 'PUT',
      mimeType: fileMeta.type,
    };

    const fileTransfer: FileTransferObject = this.transfer.create();
    return fileTransfer.upload(file.path, uploadUrl, options);
  }

Hope this explanation proves helpful. :)

Similar questions

If you have not found the answer to your question or you are interested in this topic, then look at other similar questions below or use the search

Instructions on creating an individual DropdownIndicator component with React-select for the purpose of reusability in different sections of the project

The code below functions properly when the DropdownIndicator component is kept in the same file. However, I am interested in separating DropdownIndicator into its own file so that it can be reused. This way, it can be used as a separate component and incl ...

The functionality of fetching website titles using Ajax/jQuery is experiencing some limitations

Below is a code snippet for a simple website title getter: $( document ).ready(function() { $("#title").click(function() { var SubURL = $("#input").val(); $.ajax({ url: "http://textance.herokuapp.com/title/"+SubURL+"/", complete: function(da ...

Build a flexible Yup validation schema using JSON data

I am currently utilizing the power of Yup in conjunction with Formik within my react form setup. The fields within the form are dynamic, meaning their validations need to be dynamic as well. export const formData = [ { id: "name", label: "Full n ...

Exploring the efficiency of AngularJS when binding to deeply nested object properties

Are there any performance differences to consider when data binding in Angularjs between the following: <div>{{bar}}</div> and <div>{{foo.bar}}</div>? What about <div>{{foo.bar.baz.qux}}</div>? Our team is working o ...

Stopping free jqgrid disabled toolbar buttons from reacting to mouse clicks can be achieved by implementing specific coding techniques that

When using Free jqgrid, toolbar disabled buttons may trigger click events on mouse clicks which can lead to invalid code execution. To demonstrate this, open the page below in Chrome and click on a disabled inline edit or pager button. A rectangle will app ...

Correcting W3C validation issues is essential

I am encountering errors in my W3C validation process. Even though I have set <!DOCTYPE HTML> for my page, I continue to experience issues as shown in the image below. I have been trying to troubleshoot and resolve these errors without much success ...

Tips for sending information to select2 version greater than 4.0

I'm exploring the use of select2 for the first time and wondering if someone could assist me. I want to pull data from a static array. Can you offer any guidance on how to achieve this? This is the code I currently have: $(document).ready(function( ...

"Encountering a blank page in React Router when transitioning between separate projects

I've come across some discussions about a similar issue like this one, but I haven't been able to resolve my problem. In my initial project, I can smoothly navigate between its pages. However, when I created a second project hosted in a subdirec ...

Customizing external elements with React's inline styling feature

Trying to use React to style elements generated by a third-party library has been a challenge. In the snippet below, I was able to achieve the desired styling using CSS, but now I am looking to accomplish the same using JavaScript. This way, users can defi ...

Canvas flood fill is having trouble reaching the edges

While utilizing a flood fill algorithm to fill circles drawn on the canvas, I've encountered an issue where the algorithm fails to fill right up to the edge of the circle. Here is the implementation of the algorithm based on this blog post: function ...

Guide on updating the form structure with ajax

Lately, I've been working on a contact module with 3 columns: name, email, and phone. There's also a +1 button that adds a new row to input another contact using ajax. However, a problem arises when updating the structure as the data in the old c ...

The route param is throwing a "Cannot read property 'name' of undefined" error, indicating that the property

Currently, I am enrolled in an ExpressJS course on TUTS+ From the video tutorial, I have implemented the following code snippet (excerpt from video): var express = require('express'), app = express(); app.get('/name/:name', funct ...

Overlaying content: Innovative dropdown menu design

My goal is to create a dropdown box that overlays the content of a div when an icon within it is clicked. However, currently, the dropdown box is pushing down the content of the div instead of overlaying it. I have tried adjusting my CSS by setting some el ...

"Relating to meteorjs, admin users are akin to those in

Looking for a package or tutorial to create admin users similar to Django. I want to be able to create superusers through the terminal and have the ability to personalize user schemas with Collection2. Additionally, I would like to remove the option for ...

Buefy: Secure the header of the table in place while allowing the rows to scroll freely

How can I make the header of the table component stay fixed while allowing only the rows to scroll? ...

Looking for help understanding a basic piece of code

$('#ID').on('click', function() { if(!CommonUtil.compareDateById('startDt','endDt',false, false, true)) { return false; } var cnt = 0; if(!CommonUtil.isNullOrEmptyById('startD ...

How many intricate objects are instantiated in memory when running the code snippet provided above?

When looking at the given code, how many complex objects can we identify in memory? function Foo() { this.one = function() { return "one"; } } var f = new Foo(); Foo.two = function() { return "two"; }; Here's what I see: The Foo co ...

Encountering an issue with Material-UI and Next.js: "TypeError: theme.spacing is not a function

Encountering an issue after modifying _app.js to dynamically generate a material UI theme. I've been following the implementation example provided by the material-ui team at: https://github.com/mui-org/material-ui/tree/master/examples/nextjs. To summ ...

Having trouble with sending a JSON post request in Flask?

I have a setup where I am utilizing React to send form data to a Flask backend in JSON format. Here is an example of the code: add_new_user(e){ e.preventDefault() var user_details = {} user_details['fname'] = this.state.first_name user_d ...

Create original identifiers for dynamically generated material

I have developed a custom invoice tool that has the capability to dynamically add rows. Here is the code snippet responsible for generating new rows: $("#addrow").click(function(){ $(".item-row:last").after('<tr class="item-row"><td> ...