Javascript 如何将 svg 画布保存到本地文件系统
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/2483919/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
How to save svg canvas to local filesystem
提问by dr jerry
Is there a way to allow a user, after he has created a vector graph on a javascript svg canvas using a browser, to download this file to their local filesystem?
有没有办法允许用户在使用浏览器在 javascript svg 画布上创建矢量图后,将此文件下载到他们的本地文件系统?
SVG is a total new field for me so please be patient if my wording is not accurate.
SVG 对我来说是一个全新的领域,所以如果我的措辞不准确,请耐心等待。
采纳答案by zneak
It might be possible using the regular "Save" browser command, but it won't just save the SVG canvas, it will save the whole page.
可能可以使用常规的“保存”浏览器命令,但它不仅会保存 SVG 画布,还会保存整个页面。
I believe your best bet is to use AJAX and send the whole SVG XML data as POST data to a server script, and have that script just send back the POST data with the header Content-Disposition: attachment; filename=yourfile.svg.
我相信您最好的选择是使用 AJAX 并将整个 SVG XML 数据作为 POST 数据发送到服务器脚本,并让该脚本仅将带有 header 的 POST 数据发送回Content-Disposition: attachment; filename=yourfile.svg。
(Under PHP, you can get the raw POST contents with file_get_contents('php://input').)
(在 PHP 下,您可以使用file_get_contents('php://input').获取原始 POST 内容。)
回答by The Who
You can avoid a round trip to the server.
您可以避免往返服务器。
Base64 encode your SVG xml.
Base64 编码您的 SVG xml。
Then generate a link to that data. The user can right click on to save it locally.
然后生成指向该数据的链接。用户可以右键单击以将其保存在本地。
// 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>"));
}
The img tag works in Webkit, the link works in Webkit & Firefox, and may work in any browser which supports data-uri
img 标签在 Webkit 中有效,链接在 Webkit 和 Firefox 中有效,并且可以在任何支持 data-uri
回答by Eli Grey
Using FileSaver.js
saveAs(new Blob([SVG_DATA_HERE], {type:"application/svg+xml"}), "name.svg")
回答by mac13k
There is no need to do base64 encoding - you can create a link with raw SVG code in it. Here is a modified function encode_as_img_and_link() from The_Who's answer:
无需进行 base64 编码 - 您可以在其中创建包含原始 SVG 代码的链接。这是 The_Who 的回答中修改后的功能 encode_as_img_and_link() :
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')
);
}
回答by dr jerry
With FileSaverfrom Eli Grey I got it working (chrome):
使用Eli Gray 的FileSaver,我可以正常工作(镀铬):
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 is from keith woods jquery's svg.
SVG 来自基思伍兹 jquery 的 svg。
回答by user2053898
// 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);
});
回答by rmsylvester
I recently found this Chrome plugin http://nytimes.github.io/svg-crowbar/. It's a bit buggy for my needs but essentially works.
我最近发现了这个 Chrome 插件http://nytimes.github.io/svg-crowbar/。这对我的需求来说有点问题,但基本上有效。
I had previously made a solution similar to the accepted answer which involved a serverside script but it's quite long winded and also had the problem that all the styles had to be inline in the markup. Crowbar seems to take care of that for you, which is nice.
我以前做过一个类似于已接受的答案的解决方案,它涉及服务器端脚本,但它很冗长,而且还有一个问题,即所有样式都必须在标记中内联。Crowbar 似乎会为您解决这个问题,这很好。
回答by David
I'm replying to this topic, even though it's a few years old, because the recent convergence of web browsers in their support for SVG and other relevant behaviour has produced renewed interest in SVG and allows a 'universal' answer to the question. In essence zneak's approach is correct but, in my opinion, terse (i.e. it took me a while to get it working for myself). I also think that his reference to AJAX is either unnecessary or not what I understand by AJAX (= uses an XMLHttpRequest). I shall therefore provide a more detailed answer using pure JavaScript (i.e. without JQuery or any other library) and provide server code for Java, Perl and PHP.
我正在回复这个话题,尽管它已经有几年的历史了,因为最近 Web 浏览器在支持 SVG 和其他相关行为方面的融合使人们对 SVG 重新产生了兴趣,并允许对这个问题提供一个“通用”的答案。本质上,zneak 的方法是正确的,但在我看来,简洁(即我花了一段时间才让它为自己工作)。我还认为他对 AJAX 的引用要么是不必要的,要么不是我对 AJAX 的理解(= 使用 XMLHttpRequest)。因此,我将使用纯 JavaScript(即没有 JQuery 或任何其他库)提供更详细的答案,并提供 Java、Perl 和 PHP 的服务器代码。
(1) Have the (dynamically generated) SVG content in your HTML page enclosed in a div with a unique ID, e.g.
(1) 将 HTML 页面中的(动态生成的)SVG 内容包含在具有唯一 ID 的 div 中,例如
<div id="svg"><svg...>SVG content</svg></div>
<div id="svg"><svg...>SVG content</svg></div>
(2) Include a button to invoke the JavaScript function, e.g.
(2) 包含一个按钮来调用 JavaScript 函数,例如
<button onclick="sendSVG();">Save as SVG File</button>
<button onclick="sendSVG();">Save as SVG File</button>
(3) Include the JavaScript function named in your button markup:
(3) 在按钮标记中包含命名的 JavaScript 函数:
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) Write a server app to accept your SVGtext post request and return as image/svg+xml using Content-Disposition to specify an attachment. Working code in three languages is presented, although I am not a Perl programmer and have never used PHP in anger.
(4) 编写一个服务器应用程序来接受您的 SVGtext 发布请求,并使用 Content-Disposition 指定附件以 image/svg+xml 形式返回。提供了三种语言的工作代码,虽然我不是 Perl 程序员,也从未在愤怒中使用过 PHP。
Java Servlet
Java 小服务程序
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);
}
Perl CGI
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
<?php
$svgText = $_POST['svgText'];
header('Content-type: image/svg+xml');
header('Content-Disposition: attachment; filename="image.svg"');
print "$svgText";
?>
I have used a hard-coded name for the image here (image.svg), but actually pick up a discriptor of the dynamic content I generate from the page (using a div and an ID again, and document.getElementById('graphName').textContent).
我在此处为图像使用了硬编码名称 (image.svg),但实际上选取了我从页面生成的动态内容的描述符(再次使用 div 和 ID,以及document.getElementById('graphName').textContent)。
This has been tested on Mac Safari 9, Firefox 42, Chrome 47, Opera 34, and Windows7/IE 11 and Windows10/Edge and in each case the svg file is downloaded or one is prompted to download it. The resulting files will open in, e.g. Adobe Illustrator or whatever other application you have set to open svg files.
这已经在 Mac Safari 9、Firefox 42、Chrome 47、Opera 34、Windows7/IE 11 和 Windows10/Edge 上进行了测试,并且在每种情况下都会下载 svg 文件或提示下载它。生成的文件将在例如 Adobe Illustrator 或您设置为打开 svg 文件的任何其他应用程序中打开。
A real-world example of this (if you consider academic research real-world) is at http://flyatlas.gla.ac.uk/MidgutAtlas/index.htmlin the Gene section.
一个真实世界的例子(如果你考虑学术研究真实世界)是在http://flyatlas.gla.ac.uk/MidgutAtlas/index.html的基因部分。
回答by Nood
Yes is it possible. Use jquery.svg http://keith-wood.name/svgRef.htmland post the svg xml data using the function svg.toSVG() (writing into a hidden field on submit). Have the php save and convert to raster using imagemagick (convert image.svg image.png) then force the file to download using header("Content-Type: application/octet-stream") and readfile the image.
是的,这是可能的。使用 jquery.svg http://keith-wood.name/svgRef.html并使用函数 svg.toSVG() 发布 svg xml 数据(在提交时写入隐藏字段)。使用 imagemagick (convert image.svg image.png) 将 php 保存并转换为光栅,然后使用 header("Content-Type: application/octet-stream") 强制下载文件并读取图像。
回答by Bill Bronson
I maybe discovered a better way for not forcing the user to press right click "save image as". just live draw the canvas base64 code into the href of the link and modify it so the download will start automatically. i dont know if its universal browser compatible but it should work with the main/new browsers.
我可能发现了一种更好的方法来不强迫用户按右键单击“将图像另存为”。只需将画布 base64 代码实时绘制到链接的 href 中并对其进行修改,以便自动开始下载。我不知道它的通用浏览器是否兼容,但它应该适用于主要/新浏览器。
var canvas = document.getElementById('your-canvas');
if (canvas.getContext) {
var C = canvas.getContext('2d');
}
$('#your-canvas').mousedown(function(event) {
// feel free to choose your event ;)
// just for example
// var OFFSET = $(this).offset();
// var x = event.pageX - OFFSET.left;
// var y = event.pageY - OFFSET.top;
// standard data to url
var imgdata = canvas.toDataURL('image/png');
// modify the dataUrl so the browser starts downloading it instead of just showing it
var newdata = imgdata.replace(/^data:image\/png/,'data:application/octet-stream');
// give the link the values it needs
$('a.linkwithnewattr').attr('download','your_pic_name.png').attr('href',newdata);
});
feel free to wrap the a around anything you want, hope that helps a bit
随意将 a 包裹在你想要的任何东西上,希望能有所帮助

