атрибут загрузки тега href - как заставить его принудительно загружать внешнее размещенное изображение? - PullRequest
0 голосов
/ 23 сентября 2018

Я хочу создать ссылку <a href, которая при нажатии заставляет ваш браузер открыть диалог «Сохранить как».Использование атрибута HTML5 download должно иметь такое поведение во всех современных браузерах.

Когда целью является файл размещенного изображения извне , это не работает.Ссылка <a href будет переходить к изображению вместо его загрузки.(Протестировано с использованием изображений, размещенных на Imgur и Tumblr)

image


  
image

Similar HTML code does work if the image is hosted locally on your server, for example


  
image

Another example - this will work in the W3Schools Tryit Editor , но не будет работать, если вы скопируете HTML-код в другую изолированную программную среду, например JSFiddle

<a href="https://www.w3schools.com/images/myw3schoolsimage.jpg" download>
  <img src="https://www.w3schools.com/images/myw3schoolsimage.jpg" width="104" height="142">
</a>


Возможные причины исследования:

  • Неверное изображение URL: нет, URL-адрес хороший, вы можете открытьURL в виде обычного изображения в вашем браузере
  • Ссылки с https: не могут использоваться таким образом из-за безопасности: нет, URL с https: подходит, если URL указываетв тот же домен, протестировано в W3Schools Tryit Editor
  • Перенаправление на стороне сервера: ссылка http://... может быть перенаправлена ​​на https://..., так что может быть причиной сбоя, носсылка https://... также не работает
  • Подавление атрибута загрузки на сервер конкретными хостами? это вообще возможно?атрибут загрузки должен контролировать только действия браузера на стороне клиента?

Есть ли обходные пути?Я попробовал методы загрузки Javascript, обсуждаемые здесь и здесь , но все они в конечном итоге включали действия браузера, аналогичные нажатию на ссылку href.

Отличное всестороннее обсуждение ссылок на скачивание , включая application/force-download настройку в PHP на сервере

Связанный вопрос StackOverflow: Принудительная внешняя загрузка URL (ответ кажется неправильным)

Ответы [ 2 ]

0 голосов
/ 25 сентября 2018

Оказывается, ответ таков: не может быть выполнено так, как я просил.Современные браузеры предотвращают междоменную загрузку в качестве функции безопасности.

См .: Заставка Firefox и Chrome загружать изображения под определенным именем

Принудительно загружать изображения вместооткрывающей URL-ссылки на изображение

Если загрузка должна быть идентична байту с исходным файлом, единственные решения, которые я могу найти прямо сейчас:

  1. Сервер должен сначала использовать запрос httpClient для получения целевого ресурса, сохранить его на диске локально на сервере, а затем предоставить ссылку <a href='tmp.jpg' download> с URI, который является сохраненным файлом.Или, некоторые серверные инфраструктуры могут создавать байтовый поток, имитирующий доступ к файлу, и в этом случае ресурс может быть кэширован в память вместо сохранения на диск.

    Недостатки: стоимость данных равна двойномуразмер файла (один раз, один раз), задержка туда-обратно, использование памяти сервера / файловой системы.Вероятно, каждый возможный файл со ссылкой на скачивание должен храниться локально на сервере до обслуживания страницы (или, может быть, это может быть сделано асинхронно с использованием веб-сокетов, когда файл нажимается пользователем после ссылки на скачивание, нос задержкой).Для больших файлов или серверов с высоким уровнем использования это серьезные недостатки.

  2. Откройте целевой URL-адрес на новой вкладке и дайте клиенту переключиться на эту вкладку, а затем вручную щелкните правой кнопкой мыши и выберите Сохранить как...

    Недостатки: это именно то, чего мы пытаемся избежать!

Мне все еще интересно, есть ли какой-нибудь взлом дляэто как предоставление локального URL-адреса и перенаправление сервером запроса на этот конкретный ресурс на внешний сайт.

0 голосов
/ 23 сентября 2018

Мой обходной путь: загрузите изображение на холст, затем загрузите изображение холста на локальный диск.

Код:

    <canvas id="downloadCanvas"></canvas>

    <script>
        var strDataURI = "https://78.media.tumblr.com/33f1b72778ca7352979b0f4555f08f02/tumblr_pfega8eUyH1r68v93o1_640.jpg";
        var img = new Image;
        img.crossOrigin = "Anonymous";
        img.src = strDataURI;


        var canvas = document.getElementById('downloadCanvas');
        var ctx = canvas.getContext('2d');

        img.onload = function(){

          canvas.width = img.width;
          canvas.height = img.height;
          ctx.drawImage(img,0,0);

          var dwBtn = document.getElementById("dw0");
            var dwLink = canvas.toDataURL('image/jpeg', 1.0);

          download(dwLink, "image.jpeg");
        };


    function download(dataurl, filename) {
      var a = document.createElement("a");
      a.href = dataurl;
      a.setAttribute("download", filename);
      var b = document.createEvent("MouseEvents");
      b.initEvent("click", false, true);
      a.dispatchEvent(b);
      return false;
    }

</script>

Как спросил ОП, ему нужно, чтобы захваченное изображение имелотакое же расширение.(псевдошумный код)

Измените эти строки:

  var ext = ExtensionFromUrl(url);
  var fileName = NameFromUrl(url);

      var dwLink = canvas.toDataURL('image/'+ext, 1.0);
      download(dwLink, fileName+"."+ext);

Обратите внимание: этот ответ не будет работать с изображениями GIF.Кроме того, поскольку они являются захваченными изображениями, каналы прозрачности будут потеряны!

...