Pregunta Cómo guardar el lienzo svg en el sistema de archivos local


¿Hay alguna manera de permitir que un usuario, después de haber creado un gráfico vectorial en un canvas svg de JavaScript utilizando un navegador, descargue este archivo a su sistema de archivos local?

SVG es un campo totalmente nuevo para mí, así que tenga paciencia si mi redacción no es precisa.


75
2018-03-20 17:05


origen


Respuestas:


Podría ser posible utilizando el comando de navegador "Guardar" regular, pero no solo guardará el lienzo de SVG, sino que guardará toda la página.

Creo que su mejor opción es usar AJAX y enviar toda la información SVG XML como datos POST a una secuencia de comandos del servidor, y hacer que esa secuencia de comandos envíe de vuelta los datos POST con el encabezado. Content-Disposition: attachment; filename=yourfile.svg.

(En PHP, puede obtener los contenidos primarios de POST con file_get_contents('php://input').)


15
2018-03-20 17:15



Puede evitar un viaje redondo al servidor.

Base64 codifica su SVG xml.

Luego genere un enlace a esa información. El usuario puede hacer clic derecho para guardarlo localmente.

// This example was created using Protovis & jQuery
// Base64 provided by http://www.webtoolkit.info/javascript-base64.html
// Modern web browsers have a builtin function to this as well 'btoa'
function encode_as_img_and_link(){
 // Add some critical information
 $("svg").attr({ version: '1.1' , xmlns:"http://www.w3.org/2000/svg"});

 var svg = $("#chart-canvas").html();
 var b64 = Base64.encode(svg); // or use btoa if supported

 // Works in recent Webkit(Chrome)
 $("body").append($("<img src='data:image/svg+xml;base64,\n"+b64+"' alt='file.svg'/>"));

 // Works in Firefox 3.6 and Webit and possibly any browser which supports the data-uri
 $("body").append($("<a href-lang='image/svg+xml' href='data:image/svg+xml;base64,\n"+b64+"' title='file.svg'>Download</a>"));
}

La etiqueta img funciona en Webkit, el enlace funciona en Webkit y Firefox, y puede funcionar en cualquier navegador que admita data-uri


64
2017-11-19 18:10



No es necesario hacer una codificación base64; puede crear un enlace con código SVG sin formato. Aquí hay una función modificada encode_as_img_and_link () de la respuesta de The_Who:

function img_and_link() {
  $('body').append(
    $('<a>')
      .attr('href-lang', 'image/svg+xml')
      .attr('href', 'data:image/svg+xml;utf8,' +  unescape($('svg')[0].outerHTML))
      .text('Download')
  );
}

18
2018-04-11 15:29



Utilizando FileSaver.js

saveAs(new Blob([SVG_DATA_HERE], {type:"application/svg+xml"}), "name.svg")

17
2018-03-20 19:36



Con FileSaver de Eli Gray lo conseguí trabajando (cromo):

bb = new window.WebKitBlobBuilder;
var svg = $('#designpanel').svg('get');
bb.append(svg.toSVG());
var blob = bb.getBlob("application/svg+xml;charset=" + svg.characterSet);
saveAs(blob,"name.svg");

SVG es de keith woods jquery's svg.

Html Rocks 1

Html Rocks 2


10
2018-02-15 11:43



	// save SVG
	$('#SVGsave').click(function(){
		var a      = document.createElement('a');
		a.href     = 'data:image/svg+xml;utf8,' + unescape($('#SVG')[0].outerHTML);
		a.download = 'plot.svg';
		a.target   = '_blank';
		document.body.appendChild(a); a.click(); document.body.removeChild(a);
	});


7
2017-09-16 13:08



Recientemente encontré este complemento de Chrome http://nytimes.github.io/svg-crowbar/. Es un poco problemático para mis necesidades, pero esencialmente funciona.

Previamente había hecho una solución similar a la respuesta aceptada que implicaba un script en el servidor, pero es bastante larga y también tenía el problema de que todos los estilos tenían que estar en línea en el marcado. Crowbar parece ocuparse de eso, lo cual es bueno.


5
2018-01-07 15:26



Estoy respondiendo a este tema, a pesar de que tiene algunos años, porque la reciente convergencia de navegadores web en su soporte para SVG y otros comportamientos relevantes ha producido un renovado interés en SVG y permite una respuesta 'universal' a la pregunta. En esencia, el enfoque de zneak es correcto, pero, en mi opinión, escueto (es decir, me tomó un tiempo hacerlo funcionar por mí mismo). También creo que su referencia a AJAX es innecesaria o no es lo que entiendo por AJAX (= usa un XMLHttpRequest). Por lo tanto, proporcionaré una respuesta más detallada usando JavaScript puro (es decir, sin JQuery o cualquier otra biblioteca) y proporcionaré código de servidor para Java, Perl y PHP.

(1) Tener el contenido SVG (generado dinámicamente) en su página HTML encerrado en un div con una ID única, p.

<div id="svg"><svg...>SVG content</svg></div>

(2) Incluye un botón para invocar la función de JavaScript, p.

<button onclick="sendSVG();">Save as SVG File</button>

(3) Incluya la función de JavaScript nombrada en el marcado de su botón:

function sendSVG() 
{
   var svgText = document.getElementById('svg').innerHTML;

   var form = document.createElement("form");
   form.setAttribute("method", "post");
   form.setAttribute("action", "http://path-to-your-server-app");
   form.setAttribute("accept-charset", "UTF-8");

   var hiddenSVGField = document.createElement("input");    
   hiddenSVGField.setAttribute("type", "hidden");
   hiddenSVGField.setAttribute("name", "svgText");
   hiddenSVGField.setAttribute("value", svgText);

   form.appendChild(hiddenSVGField);
   document.body.appendChild(form);
   form.submit();
}

(4) Escriba una aplicación de servidor para aceptar su solicitud de SVGtext y regrésela como image / svg + xml usando Content-Disposition para especificar un archivo adjunto. Se presenta el código de trabajo en tres idiomas, aunque no soy un programador de Perl y nunca he usado PHP con enojo.

Java Servlet

public void doPost(HttpServletRequest request, HttpServletResponse response) throws ServletException, IOException
{
   String svgText = (String) request.getParameter("svgText");
   response.setContentType("image/svg+xml");
   response.addHeader("Content-Disposition", "attachment; filename=\"image.svg\"");
   PrintWriter out = response.getWriter();
   out.println(svgText);
}

CGI de Perl

use CGI qw(:standard);
my $svgText = param('svgText');
print header(-type => "image/svg+xml",
    -content_disposition => "attachment; filename=image.svg");      
print $svgText;

PHP

<?php
   $svgText = $_POST['svgText'];
   header('Content-type: image/svg+xml');
   header('Content-Disposition: attachment; filename="image.svg"'); 
   print "$svgText";
?>

He utilizado un nombre codificado para la imagen aquí (image.svg), pero en realidad tomo un descriptor del contenido dinámico que genero de la página (usando un div y una ID nuevamente, y document.getElementById('graphName').textContent)

Esto se ha probado en Mac Safari 9, Firefox 42, Chrome 47, Opera 34, y Windows7 / IE 11 y Windows10 / Edge y en cada caso se descarga el archivo svg o se le pide a uno que lo descargue. Los archivos resultantes se abrirán, p. Adobe Illustrator o cualquier otra aplicación que haya configurado para abrir archivos svg.

Un ejemplo del mundo real de esto (si se tiene en cuenta la investigación académica en el mundo real) es a http://flyatlas.gla.ac.uk/MidgutAtlas/index.html en la sección Gene


5
2018-01-12 15:35



Sí es posible. Use jquery.svg http://keith-wood.name/svgRef.html y publicar los datos svg xml usando la función svg.toSVG () (escribiendo en un campo oculto en submit). Haga que el php guarde y convierta en raster utilizando imagemagick (convertir image.svg image.png) y luego fuerce el archivo para descargar usando el encabezado ("Content-Type: application / octet-stream") y lea la imagen.


2
2018-06-08 14:14