De TT zegt het al: wanneer ik in Firefox een url die ik terugkrijg van createObjectURL() probeer te openen, wordt het tabblad direct gesloten. Chrome toont de data zoals het hoort.
Wat ik in een uitgeklede testcase doe is het volgende:
De data voor de blob wordt door onze API als base64 aangeleverd, omgezet naar een blob en vervolgens in createObjectURL() gegooid. Voor de testcase heb ik het versimpeld naar een simpel JSON bestand. In Chrome gaat dit dus goed en zie ik de JSON, maar Firefox opent een nieuw tabblad en sluit die vervolgens direct. De logregel laat netjes zien dat er een blob is gemaakt en welke url erbij hoort. Als ik deze url kopieer en in een nieuw tabblad invoer gebeurt er ook helemaal niks.
Het stomme is, het heeft gewerkt
Wat nog stommer is, als ik een testcase maak krijg ik het probleem niet gereproduceerd: met php zorg ik voor een base64 string van het bestand, die echo ik in een scripttag zodat er verder geen rare externe calls gedaan hoeven te worden, convert de base64 naar een blob, juiste filetype erbij, exact dezelfde code als in de applicatie en voila, document.
Dat doet me vermoeden dat het probleem in de applicatie ligt (duh
), en daar maken we gebruik van Angular. Dus, daar een boel zoekwerk naar gedaan of dat conflicten heeft met blobs, niks nuttigs gevonden. Behalve dat zou je ook verwachten dat als het probleem bij Angular ligt, het in Chrome ook niet zou lukken.
De code wordt uitgevoerd nadat de data van een bestand is opgehaald. Om uit te sluiten dat het misschien aan promises/resolve ligt heb ik het ook buiten die functie geprobeerd. Nog steeds geen resultaat.
Wat ik bij mijn zoektochten veel tegenkwam zijn mensen die het bestand als download willen aanbieden; dat willen we niet. We willen dat het gewoon in een nieuw tabblad wordt geopend, en niet dat je een dialoogvenster krijgt of je een bestand wil openen of opslaan.
Het zijn ook geen popup-instellingen: behalve dat ik daar een melding van zou moeten krijgen van Firefox, zou hij dan het nieuwe tabblad überhaupt al niet moeten openen. Daarnaast heb ik al aangegeven dat ze voor die site mogen.
Edit: wat ik ook tegenkwam is revokeObjectURL(), en hoe die de referentie naar de blob verwijdert. Die roep ik nergens expliciet aan, en afaik wordt die ook nooit automatisch aangeroepen, totdat je de huidige pagina unloadt. Ik heb nog zitten experimenteren met die expliciet aanroepen, had nul effect.
Kortom, ik weet het niet meer en hoop dat iemand zometeen een soortgelijk probleem heeft gehad, een obscure oplossing heeft gevonden in een duistere hoek van het net en bereid is die te delen.
Voor de volledigheid nog even de hele functie zoals die in productie dus niet werkt:
Wat ik in een uitgeklede testcase doe is het volgende:
JavaScript:
1
2
3
4
| blob = new Blob(['{prop: "val"}'], {type: 'application/json'}); url = window.URL.createObjectURL(blob); console.log(blob, url); window.open(url, '_blank'); |
De data voor de blob wordt door onze API als base64 aangeleverd, omgezet naar een blob en vervolgens in createObjectURL() gegooid. Voor de testcase heb ik het versimpeld naar een simpel JSON bestand. In Chrome gaat dit dus goed en zie ik de JSON, maar Firefox opent een nieuw tabblad en sluit die vervolgens direct. De logregel laat netjes zien dat er een blob is gemaakt en welke url erbij hoort. Als ik deze url kopieer en in een nieuw tabblad invoer gebeurt er ook helemaal niks.
Het stomme is, het heeft gewerkt
Dat doet me vermoeden dat het probleem in de applicatie ligt (duh
De code wordt uitgevoerd nadat de data van een bestand is opgehaald. Om uit te sluiten dat het misschien aan promises/resolve ligt heb ik het ook buiten die functie geprobeerd. Nog steeds geen resultaat.
Wat ik bij mijn zoektochten veel tegenkwam zijn mensen die het bestand als download willen aanbieden; dat willen we niet. We willen dat het gewoon in een nieuw tabblad wordt geopend, en niet dat je een dialoogvenster krijgt of je een bestand wil openen of opslaan.
Het zijn ook geen popup-instellingen: behalve dat ik daar een melding van zou moeten krijgen van Firefox, zou hij dan het nieuwe tabblad überhaupt al niet moeten openen. Daarnaast heb ik al aangegeven dat ze voor die site mogen.
Edit: wat ik ook tegenkwam is revokeObjectURL(), en hoe die de referentie naar de blob verwijdert. Die roep ik nergens expliciet aan, en afaik wordt die ook nooit automatisch aangeroepen, totdat je de huidige pagina unloadt. Ik heb nog zitten experimenteren met die expliciet aanroepen, had nul effect.
Kortom, ik weet het niet meer en hoop dat iemand zometeen een soortgelijk probleem heeft gehad, een obscure oplossing heeft gevonden in een duistere hoek van het net en bereid is die te delen.
Voor de volledigheid nog even de hele functie zoals die in productie dus niet werkt:
JavaScript:
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
| $scope.downloadFile = function(attachment){ SomeModel.getAttachment(attachment.id).then(function(data){ /* Dit probeer de echte data te tonen blob = createBlob(data.base64, data.filetype); url = URL.createObjectURL(blob); window.open(url, '_blank'); */ /* Dit is een stuk simpele json, om problemen met createBlob() uit te sluiten */ var data = '{prop1: "val1", prop2: "val2"}'; var type = 'application/json'; blob = new Blob([data], {type: type}); url = URL.createObjectURL(blob); window.open(url, '_blank'); }); } |
[ Voor 4% gewijzigd door Tunaflish op 06-04-2017 10:54 . Reden: Alinea over revokeObjectURL toegevoegd ]
So long, and thanks for all the fish!