cordova-plugin-advanced-http: [Bug] [iOS] formData with blob is not sending http request

Describe the bug It is not sending any request when i am sending blob but it is working fine when i am just sending text like this form.append(“name”, “indraraj”)

System info

  • affected HTTP plugin version: [e.g. 2.3.1] HTTP : 2.3.1
  • affected platform(s) and version(s): [e.g. iOS 12.2] iOS: 12.1
  • affected device(s): [e.g. iPhone 8] iPAD 5th generation
  • cordova version: [e.g. 6.5.0] cordova
  • cordova platform version(s): [e.g. android 7.0.0, browser 5.0.3]

Are you using ionic-native-wrapper?

Minimum viable code to reproduce If applicable, add formatted sample coding to help explain your problem.

e.g.:

import { HTTP } from "@ionic-native/http/ngx";
declare const cordova: any;

 const form = new cordova.plugin.http.ponyfills.FormData()
    form.append('profile_pic', customerDetail.profile_pic);
    form.append('first_name', customerDetail.first_name);
    form.append('mobile', customerDetail.mobile);
    console.log(form, "formDataforFile")
    this._http.setDataSerializer("multipart");
    return this._http.post(
      `${environment.apiUrl}/saveWalkForm`,
      form,
      { "content-type": "application/json" }
    );

console before sending actual request

FormData

__items: Array (3)
0 Array (2)
0 "profile_pic"
1 Blob

lastModifiedDate: Thu Jan 23 2020 19:47:12 GMT+0530 (IST)

name: ""

size: 496658

type: "image/jpeg"

Blob Prototype

Array Prototype
1 Array (2)
0 "first_name"
1 "dfff"

Array Prototype
2 Array (2)
0 "mobile"
1 "3434343455"

Array Prototype

Array Prototype

FormData Prototype

Screenshots If applicable, add screenshots to help explain your problem. ionic info


Ionic:

   Ionic CLI                     : 5.2.3 (/usr/local/lib/node_modules/ionic)
   Ionic Framework               : @ionic/angular 4.11.8
   @angular-devkit/build-angular : 0.801.3
   @angular-devkit/schematics    : 8.1.3
   @angular/cli                  : 8.1.3
   @ionic/angular-toolkit        : 2.0.0

Capacitor:

   Capacitor CLI   : 1.3.0
   @capacitor/core : 1.4.0

Cordova:

   Cordova CLI       : 8.1.2 (cordova-lib@8.1.1)
   Cordova Platforms : none
   Cordova Plugins   : no whitelisted plugins (0 plugins total)

Utility:

   cordova-res : not installed
   native-run  : 0.2.8 (update available: 0.3.0)

System:

   ios-deploy : 1.9.4
   ios-sim    : 8.0.2
   NodeJS     : v12.13.0 (/usr/local/bin/node)
   npm        : 6.12.0
   OS         : macOS High Sierra
   Xcode      : Xcode 10.1 Build version 10B61

About this issue

  • Original URL
  • State: open
  • Created 4 years ago
  • Comments: 24 (6 by maintainers)

Most upvoted comments

@RomanRobot I ended up overwriting the prototype method in a bit of a hacky way until the library can be updated. I put this in main.ts:

const originalReadAsArrayBufferMethod = FileReader.prototype.readAsArrayBuffer;

FileReader.prototype.readAsArrayBuffer = function(args) {
  const originalFileReader = this['__zone_symbol__originalInstance'];
  if (originalFileReader) {
    originalFileReader.onloadend = () => {
      this.result = originalFileReader.result;
      this.onload();
    }
    originalFileReader.readAsArrayBuffer(args);
  } else {
    originalReadAsArrayBufferMethod(args);
  }
}

@silkimen I believe this is due to an ongoing issue with ionic/capacitor apps and Angular’s Zone library. I implemented this suggested solution in your library, and it fixed my issue. Please let me know if you would like me to submit a PR. Thanks

Edit: The fix actually needs to listen to onloadend as well, instead of onload. Otherwise the file result doesn’t get saved.

I’m having the same issue with Ionic + Capacitor + Angular on an Android device. Sending FormData works well but the second I add a Blob to the FormData, the http request never gets send and i have no error.

@bsbechtel thanks for the hacky way after I had spent days on it and saw this eventually. It deserves a PR.

@bsbechtel Freakin’ awesome! That got me unblocked on that finally. Thank you!

I wasn’t able to get it working tonight but I got a bit further by stepping through things. One of the issues was that I was using FormData. It passes the dependencyValidator.checkFormDataInstance(data); check in processFormData because it has an entries function, but the iterator that it returns reads the File as a string. So when it does the instanceof check here it’s already a string type with the value [object Object]. To fix that I switched to the ponyfills.FormData mentioned in the documentation, even though the FormData I was using already had an entries function.

declare var cordova;
...
new cordova.plugin.http.ponyfills.FormData()

The issue I am running into now is that when I am debugging, the File constructor from cordova-plugin-file is different from the standard one. It doesn’t accept the file content as a string.

/**
 * Constructor.
 * name {DOMString} name of the file, without path information
 * fullPath {DOMString} the full path of the file, including the name
 * type {DOMString} mime type
 * lastModifiedDate {Date} last modified date
 * size {Number} size of the file in bytes
 */

var File = function (name, localURL, type, lastModifiedDate, size) {
    this.name = name || '';
    this.localURL = localURL || null;
    this.type = type || null;
    this.lastModified = lastModifiedDate || null;
    // For backwards compatibility, store the timestamp in lastModifiedDate as well
    this.lastModifiedDate = lastModifiedDate || null;
    this.size = size || 0;

    // These store the absolute start and end for slicing the file.
    this.start = 0;
    this.end = this.size;
};

So I tried passing the file as a Blob again

formData.append('file', new Blob([fileContent]), fileName);

or

formData.append('file', new Blob([fileContent], { type: 'text/html' }), fileName);

or

const textEncoder = new TextEncoder();
formData.append('file', new Blob([textEncoder.encode(fileContent).buffer]), fileName);

but FileReader.onload is never triggered in processFormDataIterator when it’s a Blob type so it doesn’t push the file entry for serialization.

While debugging I noticed that window.File has that weird constructor I pasted above but window.Blob doesn’t have a constructor. Not sure if that has to do with it but that is as far as I got tonight. Empty Blob constructor