Schreyers
Schreyers

Reputation: 71

IOS 13 XMLHttpRequest Blob audio/mpeg returns as text/html

The code I have used to work on both Android and IOS, until I had to make the IOS version on ionic use WKWebViewOnly.

This is the code that was working on IOS (still works on Android):

var type = window.PERSISTENT;
var size = 50*1024*1024; // 50MB
window.requestFileSystem(type, size, successCallback, errorCallback);

function successCallback(fs) {

    window.resolveLocalFileSystemURL(app.folder, function(dirEntry) {

        dirEntry.getFile(mix_name, {create: true}, function(fileEntry) {
            
            fileEntry.createWriter(function(fileWriter) {

                fileWriter.onwriteend = function(e) {

                   alert('Write success');
                    
                };

                fileWriter.onerror = function(e) {
                   alert('Write failed: ' + e.toString());
                };

                var oReq = new XMLHttpRequest();

                // Make sure you add the domain name to the Content-Security-Policy <meta> element.
                oReq.open("GET", "https://domain-to-get-file.com/path/to/file.mp3", true);

                // Define how you want the XHR data to come back
                oReq.responseType = "blob";

                oReq.onload = function (oEvent) {
                    var blob = oReq.response; // Note: not oReq.responseText

                    blob = blobToFile(blob, fileName);

                    fileWriter.write(blob);

                };

                oReq.send(null);

            }, errorCallback);
        }, errorCallback);
    }, errorCallback);
}

function errorCallback(error) {
  alert("ERROR: " + error.code)
}

function blobToFile(theBlob, fileName) {
    // A Blob() is almost a File() - it's just missing the two properties below which we will add
    theBlob.lastModifiedDate = new Date();
    theBlob.name = fileName;
    return theBlob;
}

In my index.html I have the meta tag:

<meta http-equiv="Content-Security-Policy" content="
    default-src * data: cdvfile: gap: blob:;
    script-src 'self' 'unsafe-inline' *.domain-to-get-file.com; 
    style-src 'self' 'unsafe-inline';">

And the plugins I have used are:

<plugin name="cordova-plugin-wkwebview-engine" source="npm" />
<plugin name="cordova-plugin-wkwebview-file-xhr" spec="~2.1.4" />

Works fine on Android but not on IOS 13.

I think i'm missing a security thing, but I have no idea how to fix that.

Thanks :)

Upvotes: 1

Views: 463

Answers (1)

Schreyers
Schreyers

Reputation: 71

This was a miss leading issue, but for anyone stumbling upon it.

The fix was to switch from using XMLHttpRequest to Fetch: https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

I had no clue about Fetch until I saw this video: https://www.youtube.com/watch?v=tc8DU14qX6I&list=PLRqwX-V7Uu6YxDKpFzf_2D84p0cyk4T7X

and you will also need this: https://www.youtube.com/watch?v=zswi0cPMxsU to solve the CORS issue

I also did removed the plugins:

<plugin name="cordova-plugin-wkwebview-engine" source="npm" />
<plugin name="cordova-plugin-wkwebview-file-xhr" spec="~2.1.4" />

and adding this all-in-one plugin seemed to fix the issue.

https://www.npmjs.com/package/cordova-plugin-wkwebview-ionic-xhr

Added these two preferences in the ios platform in config.xml

<preference name="allowFileAccessFromFileURLs" value="true" />
<preference name="allowUniversalAccessFromFileURLs" value="true" />

Upvotes: 1

Related Questions