How to save svg canvas to local filesystem

前端 未结 16 1343
南旧
南旧 2020-11-27 10:10

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?

SVG

相关标签:
16条回答
  • 2020-11-27 10:11

    You can avoid a round trip to the server.

    Base64 encode your 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

    0 讨论(0)
  • 2020-11-27 10:11

    To answer my own question:

    Another possibility though not the nicest is to display the serialized contents on the webpage and have the user select, copy and paste that. This after investigating eli grey's solution.

    0 讨论(0)
  • 2020-11-27 10:14

    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.

    (1) Have the (dynamically generated) SVG content in your HTML page enclosed in a div with a unique ID, e.g.

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

    (2) Include a button to invoke the JavaScript function, e.g.

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

    (3) Include the JavaScript function named in your button markup:

    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.

    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);
    }
    

    Perl CGI

    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";
    ?>
    

    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).

    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.

    A real-world example of this (if you consider academic research real-world) is at http://flyatlas.gla.ac.uk/MidgutAtlas/index.html in the Gene section.

    0 讨论(0)
  • 2020-11-27 10:15

    You can't save anything with javascript to the local filesystem, what you should do is send the contents of the canvas to the server and make the user download and save that.

    0 讨论(0)
  • 2020-11-27 10:19

    Yes is it possible. Use jquery.svg http://keith-wood.name/svgRef.html and 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.

    0 讨论(0)
  • 2020-11-27 10:19

    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.

    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

    0 讨论(0)
提交回复
热议问题