Downloading Files from Your Cordova Application to Your Device

I am currently developing a mobile application using Cordova. In the app, there is a tutorial available in .docx format that needs to be accessed on the device. The current method involves the user clicking a button to view the tutorial document, which then opens in any compatible application for .docx files installed on the device. Strangely, this functionality works smoothly on Android devices but encounters an issue on iOS. An error code 3 is thrown during the download process, specifically within the FileTransferError, but this occurs only on iOS and not on Android. I have conducted research on this matter, but most resources focus on downloading from web servers. Can anyone explain why I am encountering error code 3 on iOS while experiencing no issues on Android?

Below is the code snippet triggered when the tutorial viewing button is clicked:

function downloadTutorial() {
    var userAgent = navigator.userAgent || navigator.vendor || window.opera;
    if (userAgent.indexOf("Android") > -1) {
        window.resolveLocalFileSystemURL(cordova.file.externalDataDirectory, function (directoryEntry) {
            directoryEntry.getFile("app-tutorial.docx", { create: true }, function (fileEntry) {

            download(fileEntry, encodeURI(cordova.file.applicationDirectory + "www/docs/app-tutorial-en.docx"));
            }, function(e1){
                console.error(`get file failed`);
                console.log(e1);
            });
        }, function(e) {
            console.error(`write failed`);
            console.log(e);
        });
    }
    else if ((userAgent.indexOf("iPad") > -1 || userAgent.indexOf("iPhone") > -1 || userAgent.indexOf("iPod") > -1) && !window.MSStream) {
        window.resolveLocalFileSystemURL(cordova.file.documentsDirectory, function (directoryEntry) {
            console.log(directoryEntry);
            directoryEntry.getFile("app-tutorial.docx", { create: true }, function (fileEntry) {
                console.log(fileEntry);

                download(fileEntry, encodeURI(cordova.file.applicationDirectory + "www/docs/app-tutorial-en.docx"));
            }, function(e1){
                console.error(`get file failed`);
                console.log(e1);
            });
        }, function(e) {
            console.error(`write failed`);
            console.log(e);
        });
    }
}

This section details the download function used:

function download(fileEntry, uri) {
    var fileTransfer = new FileTransfer();
    var fileURL = fileEntry.toURL();
    console.log(fileURL);
    var options = new FileUploadOptions();
    options.headers = { Connection: "close" };

    fileTransfer.download(uri, encodeURI(fileURL), function (entry) {
        console.log("Successful downloaded tutorial file.");

        cordova.plugins.fileOpener2.open(
            fileURL,
            "application/vnd.openxmlformats-officedocument.wordprocessingml.document", {
                error : function(e) {
                    console.error(`Error status: ${e.status} - Error message: ${e.message}`);
                },
                success : function () {
                    console.log('file opened successfully');
                }
            }
        );
    },
    function (error) {
        console.error(`file transfer error ${error}`); // a FileTransferError is logged here with the source, destination and error code 3
    }, false, options);
}

The following excerpt is extracted from config.xml:

<widget id="" version="0.18.0" xmlns="http://www.w3.org/ns/widgets" xmlns:cdv="http://cordova.apache.org/ns/1.0">
<name></name>
<description>

</description>
<author email="" href="">

</author>
<content src="index.html" />
<plugin name="cordova-plugin-whitelist" spec="1" />
<plugin name="cordova-plugin-console" spec="1.0.3" />
...
</widget>

Answer №1

After much experimentation, I discovered a solution for iOS using cordova-plugin-inappbrowser. By implementing

cordova.InAppBrowser.open("docs/app-tutorial-en.docx", "_blank", { location: "no", closebuttoncaption: "Done" });
, the issue was resolved on iOS devices. However, the same approach failed to work on Android. As a workaround, I decided to utilize the code provided in the original question for Android and the alternative code mentioned in this response for iOS. Should anyone have a more efficient method, I am definitely open to exploring other suggestions.

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

Transferring information between different parts of a system

I have created a component that includes a state called chosenGenre, along with a function that updates this state based on button clicks. My goal is to access the updated state (which is of type string) in another component. This is the initial componen ...

Easy Registration Page using HTML, CSS, and JavaScript

In the process of creating a basic login form using HTML and CSS, I'm incorporating Javascript to handle empty field validations. To view my current progress, you can find my code on jsfiddle My goal is to implement validation for empty text fields ...

Steer clear of making changes to a JavaScript array

Here is my code snippet: let traces = { ref: null, min: null, max: null, avg: null }; let learning = { "Application": "b3", "t": [ { "d": 2, "BinaryType": "Current" }, { "d": 3, ...

Using Socket.emit in Ionic may not function as expected

Currently, I'm in the process of establishing a socket connection between my Ionic application and a socket server that I've constructed. The socket connection seems to encounter issues specifically when running the app on an iOS simulator u ...

Ways to substitute a single parameter within Vue.js router

We are working on a complex multi-level multi-tenant application, where the hostname is used to identify the 'supplier' account and the customer account is included in the URL structure. For example, our routes are structured like this: /:local ...

Retrieve user-specific information through a modal when the API is clicked

I am currently facing an issue where I am only able to retrieve the user ID or first name, but not all the details at once in the modal popup. My goal is to display specific user data in the modal. Here is the HTML code: <table class="table table- ...

Using React JS to send an object as an argument to an action function

How do I pass the "fields" object to the action "createPost" after creating it with validation in a form? Do I need to use "props" or could it be related to the dispatcher line? import React, { Component } from 'react'; import Header from ' ...

Using the JavaScript moment library, you can easily convert a value into seconds

Could moment.js be used to format var timeValue = '65' into 01:05? While easier to format as ('HH:MM:SS'), passing a variable as 65 and converting it into ('mm:ss') results in '01:00' instead of '01:05'. C ...

Transferring information via interface with a null reference in Android Studio

Fragment public class page2_saved_notes extends Fragment { public static final String SAVE = "MyPrefsArrays"; private String mTitleArray = "titlesArray"; private String mNotesArray = "notesArray"; ArrayList<String&g ...

Tips for dynamically assigning a class to a span tag within a popover tooltip that utilizes Bootstrap Tagsinput based on the result of an if-else statement

//The contents of my JavaScript file are as follows: $mytag.popover({ html:true, trigger: hover, container: $mytag, template: '<div class="popover" role="showDetails">' + ...//other '</div> ...

The ng-app directive for the Angular project was exclusively located in the vendor.bundle.js.map file

Currently, I am diving into an Angular project that has been assigned to me. To get started, I use the command "gulp serve" and then access the development server through Chrome by clicking on "http://localhost:3000". During my investigation in Visual Stu ...

Preventing page reload by using event.preventDefault() does not work with Ajax Form

I've been working on a code snippet to submit a form using Ajax without any page reloads: $( document ).on('submit', '.login_form', function( event ){ event.preventDefault(); var $this = $(this); $.ajax({ data: ...

Creating a Turn.js interactive book similar to the provided example?

I'm in the process of creating a book using turn.js with Jquery and everything is going smoothly so far. However, I could use some assistance. I am trying to achieve the look of a hard-backed journal-type book similar to the example provided here . My ...

Display a loading spinner on the browser while the form is being submitted

My current project involves using AJAX to retrieve data and populate a form. The data being fetched is quite large, resulting in a delay as it is fetched from the database and filled into the form fields. During this process, I display a loading icon to in ...

Issue with Barcode scanning output when using the AVFoundation framework

I have been utilizing the AVFoundation framework in iOS 7 for Barcode scanning. While it generally works correctly, I am encountering incorrect results with certain Barcodes. I have included the code file and Barcode causing the issue. Please review them ...

What is the best practice for updating state immutably in React using Redux and Redux Toolkit?

As I delve into learning Redux, I've come across a method called addPosts which allows me to add posts to my list. Here's how I'm implementing it: import { createSlice } from "@reduxjs/toolkit"; const initialState = [{ number: 1 } ...

Discovering the best way to interact with a REST API using Android

I am currently working on developing a mobile app using Android to consume a local REST API. I have set up a REST server in Eclipse and it is functioning properly. However, I am facing an issue with my Android Studio client where clicking on the button d ...

Tips for preventing timeouts when posting data to Heroku servers

I have a Ruby on Rails application deployed on Heroku. The app includes 8 optional text fields that users can choose to fill or leave empty as needed. However, the more text fields a user fills out, the heavier the processing load on my app. If there are ...

What steps should be followed to establish a well-organized framework for making an API call using

I am looking to streamline the process of making API calls using the OkHttp library. Having to include the same okhttp call code in every screen of my application seems redundant and inefficient. Here is an example of how I currently make API calls using o ...

Highlighting the home page in the navigation menu even when on a subroute such as blog/post in the next.js framework

After creating a navigation component in Next JS and framer-motion to emphasize the current page, I encountered an issue. The problem arises when navigating to a sub route like 'localhost:3000/blog/post', where the home tab remains highlighted i ...