cordova-plugin-file icon indicating copy to clipboard operation
cordova-plugin-file copied to clipboard

Do not overwrite standard File API

Open mark-veenstra opened this issue 5 years ago • 22 comments

Feature Request

Motivation Behind Feature

This plugin overwrites standard Web API implementations like:

Plugin Clobber Standard Web API
window.File File
window.FileReader FileReader
window.ProgressEvent ProgressEvent

This causes issues for example with the E2E testing tool Cypress. Specifically the Cypress plugin cypress-file-upload, which relies on the default File API implementation.

Feature Description

Do not overwrite the standard API. It seems that the plugin itself using it's own require method to include the correct JS file. But the plugin.xml file also overwrites the standard Web implementation.

Drawbacks would be that people that are using these exposed overwritten API's would have a problem or need to re-write code. That being said, the adjusted File API that this plugin needs could still be exposed on the window object, but not overwrite the standard API, for example in an own namespace or something like that.

For example expose:

  • window.File within a cordova namespace, like window.cordova.File

Alternatives or Workarounds

Alternatives would be that tools like Cypress or any other codebase that needs the standard API include a polyfill to get the standard API back again.

mark-veenstra avatar May 20 '19 18:05 mark-veenstra

Cordova Plugin File was implemented before (most of) the browsers had the specification implemented, which is why it uses the same namespace. Changing this now would be a major breaking change.

janpio avatar Jun 07 '19 14:06 janpio

We desperately need this to be fixed as well! It was a pain trying to debug why the File wasn't working as I expected it should have. Is there at least some way to get around this for the time being?

JetUni avatar Jun 18 '19 19:06 JetUni

Don't use this plugin 🤷‍♀

I can't really think of a way to easily get rid of this baggage. Do you have any suggestions?


One could probably fork this plugin and change all the clobbers tags in plugin.xml and see if it magically works, but I kind of expect loads of cross dependencies between objects. Then those would have to be updated as well, and see if it works then. unfortunately test coverage of the plugin is not very good and brittle, so you might not catch everything that breaks by using that.

janpio avatar Jun 18 '19 20:06 janpio

The problem is that it's a dependency of cordova-plugin-ionic which we just started using. I don't know that there's any easy way to get rid of this baggage either, but having known that browsers were working on implementing this, a better option might have been as @mark-veenstra mentioned and use window.cordova.File. Of course, these kinds of changes may require a major version bump.

JetUni avatar Jun 18 '19 21:06 JetUni

I think it is not a question if it is easy or not, but more if it is needed or not.

The problem lies ofcourse that everyone can overwrite and pollute the window object. And this plugin realized a great solution in the past when the window.File and window.FileReader and window.ProgressEvent didn't exist yet.

But now they do other tooling will make use of this standard API, therefore it would be better to bump to a new major version and not overwrite the standard API.

mark-veenstra avatar Jun 19 '19 06:06 mark-veenstra

I don't disagree with you both, I just know that there is nobody from the Apache Cordova team (all volunteers doing this in their free time) that needs this right now and more importantly has the time to start advocating for this and implementing it.

The plugin is the way it is because ~10 years ago this was a good decision - and now all kinds of things depend on it. And knowing how Javascript dependencies were handled over these 10 years, I am 100% sure that some of the tools using it will break because they automatically accept whatever new version we release. (Note: npm is only 9 years old)

(Another big factor is that the actual tests for this plugin currently are failing already, see https://github.com/apache/cordova-plugin-file/pull/314. Current master is only green because the last release was 1.5 years ago and tests haven't been run for 3 months)

If there was a Pull Request doing the actual work and proving what exactly has to be changed, it would probably be a lot easier for Apache Cordova to "roll with it" and put in the additional required work of getting this to a release. (Which basically tells you: Do some of the work, then I will try to support you as well as I can.)

janpio avatar Jun 19 '19 07:06 janpio

This looks like a duplicate of #265

benny-medflyt avatar Jul 18 '19 18:07 benny-medflyt

But at least you could just not completely overwrite the old API, like Zone is doing. So, before the var File = function(...), you could do something like this:

var OriginalFileApi = File;
var File = function(...){}

This would at least give us the possibility to just change some small portions of our code. I also depend on the cordova native HTTP plugin, which brings this one as dependency.

cosminadrianpopescu avatar Aug 03 '20 08:08 cosminadrianpopescu

I've created the PR #409 to achieve this.

cosminadrianpopescu avatar Aug 03 '20 09:08 cosminadrianpopescu

Is there any progress on this issue? Or any way to get original FileReader while still using this plugin? Some of others plugin I use depends on this plugin so I cannot stop using it, but now I cannot add a new functionality to my app, such as recording media. When I faced issue using media-capture plugin as it does not work with Android 10+, I thought new html5 and js features will give me an alternative, but no luck :(

julia-fix avatar Nov 09 '21 22:11 julia-fix

@July- what you can do is shim in some code before you load cordova.js in your index.html to save the old File etc.

I was very surprised when this plugin overwrote window.File and broke my app.

chr15m avatar Dec 30 '21 09:12 chr15m

I think the first step is to introduce a new access point for the Cordova API and deprecate the original one. We won't be able to remove the original one until a new major version, but we can start providing warnings for developers to migrate their code.

This way if the user wants to override the browser implementation, they have the flexibility of doing so themselves, depending on their use cases.

breautek avatar May 20 '22 16:05 breautek

@chr15m This is the way. Thanks for the hint.

FYI what I did in my index.html:

  <script>
    window.File_native = window.File; // backup the native File api because cordova-plugin-file clobbers it.
  </script>
  <script type="text/javascript" src="cordova.js"></script>
...

And when I needed to use the native File API in js:

                        let File = window.File;
                        if ("File_native" in window) { // cordova-plugin-file clobbers File(), so we backed it up at the beginning of index.html before loading cordova.js
                            // @ts-ignore
                            File = window["File_native"];
                        }
                        let otaBinary = new File([theBlob], fname);

phatpaul avatar Jul 01 '22 00:07 phatpaul

@chr15m This is the way. Thanks for the hint.

FYI what I did in my index.html:

  <script>
    window.File_native = window.File; // backup the native File api because cordova-plugin-file clobbers it.
  </script>
  <script type="text/javascript" src="cordova.js"></script>
...

And when I needed to use the native File API in js:

                        let File = window.File;
                        if ("File_native" in window) { // cordova-plugin-file clobbers File(), so we backed it up at the beginning of index.html before loading cordova.js
                            // @ts-ignore
                            File = window["File_native"];
                        }
                        let otaBinary = new File([theBlob], fname);

Tried like this, sometimes work fine, sometimes not , i didn't know why

StarHosea avatar Oct 27 '22 10:10 StarHosea

A temporary fix if there is no other plugin depending on the plugin's File & FileReader class

const nativeFile = window.File;
const nativeFileReader = window.FileReader;

window.document.addEventListener('deviceready', () => {
    window.CordovaFile = window.File;
    window.CordovaFileReader = window.FileReader;

    window.File = nativeFile;
    window.FileReader = nativeFileReader;
});

Non-conflict on the browser's native File and FileReader, CordovaFile will be the plugin's File class

kfeng0806 avatar Feb 01 '23 20:02 kfeng0806

Please fix this

LucasBourgeois avatar Jun 27 '23 10:06 LucasBourgeois

Dear @LucasBourgeois, if you want it fixed then put a fix together and submit a pull request.

chr15m avatar Jun 27 '23 13:06 chr15m

There is already one waiting to be merged. https://github.com/apache/cordova-plugin-file/pull/409

It, at least, allow to have native api's available.

Fearing breaking changes because of legacy implementation and not releasing a major version update is really a shame!

If something breaks in ppl repos, it'll be for the best as this bug is causing more bugs that not changing this is causing...

LucasBourgeois avatar Jun 27 '23 13:06 LucasBourgeois

Changing the standard API's is a really bad idea. Is there a fork that fixes this, or is there another plugin that accomplishes the same thing without changing the standard API?

jacobg avatar Jan 22 '24 17:01 jacobg