web-dev-qa-db-fra.com

Chrome 65 blocs d'origine croisée, <a download>. Solution de contournement côté client pour forcer le téléchargement?

Chrome 65 a supprimé la prise en charge de l'attribut downloadsur les éléments d'ancrage avec origine croisée hrefs:

Bloquer le cross-origine <a download>

Pour éviter ce qui est essentiellement une fuite d’informations d’origine croisée médiée par l’utilisateur, Blink ignore désormais la présence de l’attribut download sur les éléments d’ancrage comportant des attributs d’origine croisée. Notez que cela s'applique à HTMLAnchorElement.download ainsi qu'à l'élément lui-même.

Intention de supprimer | Chromestatus Tracker | Bogue de chrome

Cela casse téléchargements sans serveur (pour les ressources d'origine croisée). Il a également cassé le bouton de sauvegarde d'image de Reddit Enhancement Suite (.res-media-controls-download). RES v5.12.0 corrigé ceci en utilisant le chrome.downloads API (l'extension demande maintenant votre permission de Gérer les téléchargements)

Une solution de contournement?

13
Leeroy

Selon les URL discussionblob: et data: ne sont pas affectées. Voici donc une solution de contournement utilisant fetch et Blobs.

Support de téléchargement forcé côté client

function forceDownload(blob, filename) {
  var a = document.createElement('a');
  a.download = filename;
  a.href = blob;
  // For Firefox https://stackoverflow.com/a/32226068
  document.body.appendChild(a);
  a.click();
  a.remove();
}

// Current blob size limit is around 500MB for browsers
function downloadResource(url, filename) {
  if (!filename) filename = url.split('\\').pop().split('/').pop();
  fetch(url, {
      headers: new Headers({
        'Origin': location.Origin
      }),
      mode: 'cors'
    })
    .then(response => response.blob())
    .then(blob => {
      let blobUrl = window.URL.createObjectURL(blob);
      forceDownload(blobUrl, filename);
    })
    .catch(e => console.error(e));
}

downloadResource('https://giant.gfycat.com/RemoteBlandBlackrussianterrier.webm');

Cependant, fetch ne fonctionne que sur certaines URL. Vous pouvez obtenir une erreur CORS:

Failed to load https://i.redd.it/l53mxu6n14o01.jpg: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'https://redditp.com' is therefore not allowed access.

Il existe des extensions qui vous permettent d'intercepter, de modifier ou de supprimer les en-têtes de sécurité des sites Web:

UnXSS - Chrome Web Store

(Mais la mise en Access-Control-Allow-Origin: * a cassé YouTube pour moi)

Performance

Veuillez noter que cette approche n'est pas très performante! Parfois, les téléchargements ont stagné pendant moins d'une minute. Le reste de la page a été réactif pendant ce temps cependant. Je n'ai pas étudié la question, mais j'imagine que créer de grands blobs nécessite beaucoup de ressources.

Violentmonkey/Tampermonkey

Si votre cas d'utilisation est celui des utilisateurs, il y a GM_download(options), GM_download(url, name)

Tamp Dans Tampermonkey, il s'agit d'une fonctionnalité bêta et vous devez d'abord définir Mode de téléchargement: [API de navigateur ▾] dans Tampermonkey Dashboard> Paramètres

 Tampermonkey Dashboard > Settings > Downloads

18
Leeroy

Apparemment, la spécification web a changé à un moment donné pour interdire les téléchargements inter-origines. Ajouter l'en-tête content-disposition: attachment dans la réponse et les téléchargements inter-origines peuvent fonctionner à nouveau.

1
jbmilgrom