Сохранить BMP, содержащийся в SVG с разумным именем файла - PullRequest
1 голос
/ 19 марта 2020

У меня есть файл SVG, который содержит BMP внутри svg: image в качестве URI данных. Проблема в том, что некоторые браузеры не учитывают атрибут download="download.bmp" ссылки svg:a.

<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" 
    onload="dd();" baseProfile="full" version="1.1" height="409.6" width="1036.8">
  <script type="text/ecmascript">
function dd() {
fetch(document.getElementById('thebmp').getAttribute('xlink:href')).
  then(res =&gt; res.blob()).then(res =&gt; window.URL.createObjectURL(res)).
    then(function(x) 
    { document.getElementById('theanchor').setAttribute('href', x);});
}
  </script>
  <g transform="scale(0.2)">
    <a href="#" download="download.bmp" id="theanchor">
      <image id="thebmp" height="2048" width="2592" y="0" x="163" 
        xlink:href="data:image/x-ms-bmp;base64,...."/>
    </a>
    <g transform="translate(163,0)">
      <g id="P_1_1">
        <path d="M 130 102 l 2332 0 l 0 1844 l -2332 0 l 0 -1844" style="fill:none; 
         stroke:#66ff66; stroke-width:6px; stroke-opacity:0.75;"/>
        <text y="379" x="107" font-size="75px" fill="#66ff66" text-anchor="end">[0]</text>
      </g>
    </g>
    <g transform="translate(3110,122)">
      <g transform="scale(122)">
        <text fill="#66ff66" y="0" x="0" font-size="0.9px">blah</text>
      </g>
    </g>
  </g>
</svg>

Вы можете найти полную версию как testsvgf.svg в https://www.magentacloud.de/share/6x.svy3pz9.

Я хочу, чтобы пользователь мог сохранить изображение BMP как BMP файл (исходное содержимое svg:img xlink:href и в идеале предлагает разумное имя файла для пользователя.

Как написано, код работает только на firefox (проверено 60 и 68), предлагая сохранить с именем по умолчанию из download.bmp.

Другие браузеры ведут себя по-разному ...

Chrome предлагает / сохраняет some-crypti c -filename-без-расширения (версия 80)

Edge: ничего не делает при нажатии. При выборе Save link as в контекстном меню имя файла для загрузки увеличивается, начиная с (1).txt (я мог бы жить с контекстным меню)

Содержимое сохраненных файлов полностью корректно во всех трех браузерах. Только из Chrome и Edge вы не узнаете, что сохранили.

Добавление, например, document.getElementById('theanchor').setAttribute('download', 'another.bmp*); после document.getElementById('theanchor').setAttribute('href', x); не help

Что я делаю не так? - Заранее спасибо!

Ответы [ 2 ]

3 голосов
/ 22 марта 2020

Вы не делаете ничего плохого!

Атрибут download официально поддерживается в Масштабируемая векторная графика (SVG) 2 draft . К сожалению, это черновик . Как и многие другие веб-технологии, официальные спецификации не всегда движутся достаточно быстро (SVG 1.1 был опубликован в 2011 году), и многие браузеры стремятся принять спецификации рано.

Именно поэтому существует caniuse.com . Кстати, это показывает, что атрибут download элемента svg: a * в настоящее время поддерживается только Firefox.

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

К вашему сведению download атрибут был добавлен в июне 2016 года

Спасибо за показ странного примера того, что вы можете сделать с SVG!

2 голосов
/ 22 марта 2020

Вы можете использовать элемент ForeignObject и элемент привязки HTML, который в Chrome поддерживает атрибут загрузки.

Мы перенаправляем событие click с привязки SVG на привязку HTML, и это HTML якорь, где загрузка происходит на самом деле.

<svg xmlns:xlink="http://www.w3.org/1999/xlink" xmlns="http://www.w3.org/2000/svg" 
    onload="dd();" baseProfile="full" version="1.1" height="409.6" width="1036.8">
  <script type="text/ecmascript">
function dd() {
fetch(document.getElementById('thebmp').getAttribute('xlink:href')).
  then(res =&gt; res.blob()).then(res =&gt; window.URL.createObjectURL(res)).
    then(function(x) 
    { document.getElementById('theanchor').setAttribute('href', x);});
}
  </script>
  <g transform="scale(0.2)">
    <a href="#" onclick="document.getElementById('theanchor').click()" download="download.bmp">
      <image id="thebmp" height="2048" width="2592" y="0" x="163" 
        xlink:href="data:image/gif;base64,R0lGODlhEAAQAMQAAORHHOVSKudfOulrSOp3WOyDZu6QdvCchPGolfO0o/XBs/fNwfjZ0frl3/zy7////wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACH5BAkAABAALAAAAAAQABAAAAVVICSOZGlCQAosJ6mu7fiyZeKqNKToQGDsM8hBADgUXoGAiqhSvp5QAnQKGIgUhwFUYLCVDFCrKUE1lBavAViFIDlTImbKC5Gm2hB0SlBCBMQiB0UjIQA7"/>
    </a>
    <foreignObject width="0" height="0">
        <a xmlns="http://www.w3.org/1999/xhtml" download="download.bmp" id="theanchor"/>
    </foreignObject>
    <g transform="translate(163,0)">
      <g id="P_1_1">
        <path d="M 130 102 l 2332 0 l 0 1844 l -2332 0 l 0 -1844" style="fill:none; 
         stroke:#66ff66; stroke-width:6px; stroke-opacity:0.75;"/>
        <text y="379" x="107" font-size="75px" fill="#66ff66" text-anchor="end">[0]</text>
      </g>
    </g>
    <g transform="translate(3110,122)">
      <g transform="scale(122)">
        <text fill="#66ff66" y="0" x="0" font-size="0.9px">blah</text>
      </g>
    </g>
  </g>
</svg>
...