有没有办法让用户在使用浏览器在 javascript svg 画布上创建矢量图后,将此文件下载到他们的本地文件系统?
SVG 对我来说是一个全新的领域,所以如果我的措辞不准确,请耐心等待。
有没有办法让用户在使用浏览器在 javascript svg 画布上创建矢量图后,将此文件下载到他们的本地文件系统?
SVG 对我来说是一个全新的领域,所以如果我的措辞不准确,请耐心等待。
您可以避免往返服务器。
Base64 编码您的 SVG xml。
然后生成指向该数据的链接。用户可以右键单击将其保存在本地。
// 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>"));
}
img 标签在 Webkit 中工作,链接在 Webkit 和 Firefox 中工作,并且可以在任何支持的浏览器中工作data-uri
saveAs(new Blob([SVG_DATA_HERE], {type:"image/svg+xml"}), "name.svg")
无需进行 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')
);
}
使用常规的“保存”浏览器命令可能是可能的,但它不仅会保存 SVG 画布,还会保存整个页面。
我相信您最好的选择是使用 AJAX 并将整个 SVG XML 数据作为 POST 数据发送到服务器脚本,并让该脚本只发送带有 header 的 POST 数据Content-Disposition: attachment; filename=yourfile.svg
。
(在 PHP 下,您可以使用 . 获取原始 POST 内容file_get_contents('php://input')
。)
使用Eli Gray 的FileSaver,我得到了它的工作(chrome):
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 来自 keith woods jquery 的 svg。
// 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);
});
我最近发现了这个 Chrome 插件http://nytimes.github.io/svg-crowbar/。这对我的需要有点错误,但基本上可以工作。
我以前做过一个类似于接受的答案的解决方案,它涉及一个服务器端脚本,但它很冗长,并且还有一个问题,即所有样式都必须内联在标记中。Crowbar 似乎会为您解决这个问题,这很好。
我正在回复这个话题,尽管它已经有几年的历史了,因为最近 Web 浏览器在支持 SVG 和其他相关行为方面的融合已经引起了人们对 SVG 的新兴趣,并允许对这个问题进行“普遍”的回答。本质上,zneak 的方法是正确的,但在我看来,它很简洁(即我花了一段时间才让它为自己工作)。我还认为他对 AJAX 的引用要么是不必要的,要么不是我所理解的 AJAX(= 使用 XMLHttpRequest)。因此,我将使用纯 JavaScript(即没有 JQuery 或任何其他库)提供更详细的答案,并提供 Java、Perl 和 PHP 的服务器代码。
(1) 将 HTML 页面中的(动态生成的)SVG 内容包含在具有唯一 ID 的 div 中,例如
<div id="svg"><svg...>SVG content</svg></div>
(2) 包含一个按钮来调用 JavaScript 函数,例如
<button onclick="sendSVG();">Save as SVG File</button>
(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) 编写一个服务器应用程序来接受您的 SVGtext 发布请求,并使用 Content-Disposition 指定附件以 image/svg+xml 的形式返回。虽然我不是 Perl 程序员,也从未愤怒地使用过 PHP,但我提供了三种语言的工作代码。
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
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";
?>
我在这里为图像使用了硬编码名称(image.svg),但实际上是从页面生成的动态内容的一个描述符(再次使用 div 和一个 ID,并且document.getElementById('graphName').textContent
)。
这已经在 Mac Safari 9、Firefox 42、Chrome 47、Opera 34、Windows7/IE 11 和 Windows10/Edge 上进行了测试,并且在每种情况下都会下载 svg 文件或提示下载它。生成的文件将在 Adobe Illustrator 或您设置为打开 svg 文件的任何其他应用程序中打开。
一个真实世界的例子(如果您考虑真实世界的学术研究)位于基因部分的http://flyatlas.gla.ac.uk/MidgutAtlas/index.html。
是的,有可能吗。使用 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”)强制文件下载并读取图像。
回答我自己的问题:
另一种虽然不是最好的可能性是在网页上显示序列化的内容并让用户选择、复制和粘贴。这是在调查了 eli gray 的解决方案之后。
最兼容的方式是往返服务器。您还可以在某些浏览器中使用data: URI 。
您无法使用 javascript 将任何内容保存到本地文件系统,您应该做的是将内容发送canvas
到服务器并让用户下载并保存。
我可能发现了一种更好的方法来不强迫用户按右键单击“将图像另存为”。只需将画布 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);
});
随意将 a 包裹在您想要的任何东西上,希望对您有所帮助
$(document).ready(function(){
$("#btnDownload").click(function(){
var $container = $('#svg-container'),
// Canvg requires trimmed content
content = $container.html().trim(),
canvas = document.getElementById('svg-canvas');
// Draw svg on canvas
canvg(canvas, content);
$container.hide();
// Change img be SVG representation
var theImage = canvas.toDataURL('image/jpeg');
var a = document.createElement('a');
a.href = theImage; // xhr.response es un blob file
a.target = '_blank';
a.download = 'prueba'; // nombre del archivo.
a.style.display = 'none';
document.body.appendChild(a);
a.click();
delete a;
});//fin function
});// fin
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<script type="text/javascript" src="http://canvg.googlecode.com/svn/trunk/rgbcolor.js"></script>
<script type="text/javascript" src="http://canvg.googlecode.com/svn/trunk/canvg.js"></script>
<input id="svgData" name="svgData" type="hidden"/>
<input id="btnDownload" type="button" value="Descargar"/>
<div id='svg-container'>
<svg xmlns:xlink="http://www.w3.org/1999/xlink" version="1.1" style="font-family:'lucida grande', 'lucida sans unicode', arial, helvetica, sans-serif;font-size:12px;" xmlns="http://www.w3.org/2000/svg" width="600" height="400"><desc>Created with Highcharts 4.0.4</desc><defs><clipPath id="highcharts-5"><rect x="-75" y="-75" width="750" height="550"></rect></clipPath></defs><rect x="0" y="0" width="600" height="400" strokeWidth="0" fill="#FFFFFF" class=" highcharts-background"></rect><g style="stroke:rgba(255,255,255,0);"><path fill="rgb(255,255,255)" fill-opacity="0" d="M 59 79 L 460 61 L 456 287 L 65 330 Z" stroke-linejoin="round"></path><path fill="rgb(255,255,255)" fill-opacity="0" d="M 65 330 L 456 287 L 456 286 L 65 330 Z" stroke-linejoin="round"></path><path fill="rgb(230,230,230)" fill-opacity="0" d="M 0 0" stroke-linejoin="round"></path></g><g style="stroke:rgba(255,255,255,0);"><path fill="rgb(255,255,255)" fill-opacity="0" d="M 495 66 L 496 66 L 490 300 L 490 301 Z" stroke-linejoin="round"></path><path fill="rgb(230,230,230)" fill-opacity="0" d="M 495 66 L 460 61 L 455 287 L 490 301 Z" stroke-linejoin="round"></path><path fill="rgb(255,255,255)" fill-opacity="0" d="M 495 66 L 460 61 L 460 61 L 496 66 Z" stroke-linejoin="round"></path></g><g style="stroke:rgba(255,255,255,0);"><path fill="rgb(255,255,255)" fill-opacity="0" d="M 88 345 L 490 300 L 490 300 L 88 346 Z" stroke-linejoin="round"></path><path fill="rgb(255,255,255)" fill-opacity="0" d="M 88 346 L 490 300 L 457 287 L 65 330 Z" stroke-linejoin="round"></path><path fill="rgb(230,230,230)" fill-opacity="0" d="M 88 345 L 65 329 L 65 330 L 88 346 Z" stroke-linejoin="round"></path></g><g class="highcharts-grid" ><path fill="none" d="M 146 75 L 146 75 L 150 320 L 175 336" stroke="#C0C0C0" stroke-width="1" opacity="1"></path><path fill="none" d="M 189 73 L 189 73 L 191 316 L 217 331" stroke="#C0C0C0" stroke-width="1" opacity="1"></path><path fill="none" d="M 230 71 L 230 71 L 232 311 L 259 326" stroke="#C0C0C0" stroke-width="1" opacity="1"></path><path fill="none" d="M 271 69 L 271 69 L 271 307 L 300 322" stroke="#C0C0C0" stroke-width="1" opacity="1"></path><path fill="none" d="M 310 67 L 310 67 L 310 302 L 339 317" stroke="#C0C0C0" stroke-width="1" opacity="1"></path><path fill="none" d="M 349 66 L 349 66 L 348 298 L 378 313" stroke="#C0C0C0" stroke-width="1" opacity="1"></path><path fill="none" d="M 387 64 L 387 64 L 385 294 L 416 308" stroke="#C0C0C0" stroke-width="1" opacity="1"></path><path fill="none" d="M 424 62 L 424 62 L 421 290 L 454 304" stroke="#C0C0C0" stroke-width="1" opacity="1"></path><path fill="none" d="M 461 61 L 461 61 L 457 286 L 491 300" stroke="#C0C0C0" stroke-width="1" opacity="1"></path><path fill="none" d="M 103 77 L 103 77 L 108 325 L 131 341" stroke="#C0C0C0" stroke-width="1" opacity="1"></path><path fill="none" d="M 59 79 L 59 79 L 65 329 L 87 345" stroke="#C0C0C0" stroke-width="1" opacity="1"></path></g><g class="highcharts-grid" ><path fill="none" d="M 59 78 L 59 78 L 461 60 L 496 66" stroke="#C0C0C0" stroke-width="1" opacity="1"></path><path fill="none" d="M 61 144 L 61 144 L 460 119 L 494 127" stroke="#C0C0C0" stroke-width="1" opacity="1"></path><path fill="none" d="M 62 206 L 62 206 L 459 175 L 493 185" stroke="#C0C0C0" stroke-width="1" opacity="1"></path><path fill="none" d="M 64 269 L 64 269 L 458 232 L 492 243" stroke="#C0C0C0" stroke-width="1" opacity="1"></path><path fill="none" d="M 65 330 L 65 330 L 457 286 L 490 300" stroke="#C0C0C0" stroke-width="1" opacity="1"></path></g><g class="highcharts-axis" ><path fill="none" d="M 75 325.5 L 525 325.5" stroke="#C0D0E0" stroke-width="1" visibility="hidden"></path></g><g class="highcharts-axis" ><text x="556.96875" text-anchor="middle" transform="translate(0,0) rotate(90 556.96875 200)" class=" highcharts-yaxis-title" style="color:#707070;fill:#707070;" visibility="visible" y="200">Values</text></g><g class="highcharts-series-group" ><g class="highcharts-series" visibility="visible" transform="translate(75,75) scale(1 1)" clip-path="url(#highcharts-5)"><g r="0" stroke="#7cb5ec" stroke-width="1"><path fill="#7cb5ec" d="M 390 141 L 408 139 L 406 226 L 388 228 Z" stroke-linejoin="round"></path><path fill="rgb(99,156,211)" fill-opacity="1" d="M 390 141 L 378 137 L 376 223 L 388 228 Z" stroke-linejoin="round"></path><path fill="rgb(149,206,255)" fill-opacity="1" d="M 390 141 L 378 137 L 395 136 L 408 139 Z" stroke-linejoin="round"></path></g><g r="0" stroke="#7cb5ec" stroke-width="1"><path fill="#7cb5ec" d="M 353 56 L 372 54 L 369 230 L 351 232 Z" stroke-linejoin="round"></path><path fill="rgb(99,156,211)" fill-opacity="1" d="M 353 56 L 342 53 L 339 227 L 351 232 Z" stroke-linejoin="round"></path><path fill="rgb(149,206,255)" fill-opacity="1" d="M 353 56 L 342 53 L 360 52 L 372 54 Z" stroke-linejoin="round"></path></g><g r="0" stroke="#7cb5ec" stroke-width="1"><path fill="#7cb5ec" d="M 314 118 L 333 117 L 332 235 L 313 237 Z" stroke-linejoin="round"></path><path fill="rgb(99,156,211)" fill-opacity="1" d="M 314 118 L 303 114 L 302 231 L 313 237 Z" stroke-linejoin="round"></path><path fill="rgb(149,206,255)" fill-opacity="1" d="M 314 118 L 303 114 L 322 113 L 333 117 Z" stroke-linejoin="round"></path></g><g r="0" stroke="#7cb5ec" stroke-width="1"><path fill="#7cb5ec" d="M 275 212 L 294 210 L 293 239 L 274 241 Z" stroke-linejoin="round"></path><path fill="rgb(149,206,255)" fill-opacity="1" d="M 275 212 L 264 207 L 283 205 L 294 210 Z" stroke-linejoin="round"></path><path fill="rgb(99,156,211)" fill-opacity="1" d="M 275 212 L 264 207 L 264 236 L 274 241 Z" stroke-linejoin="round"></path></g><g r="0" stroke="#7cb5ec" stroke-width="1"><path fill="#7cb5ec" d="M 235 94 L 255 93 L 254 243 L 235 246 Z" stroke-linejoin="round"></path><path fill="rgb(99,156,211)" fill-opacity="1" d="M 235 94 L 224 90 L 224 240 L 235 246 Z" stroke-linejoin="round"></path><path fill="rgb(149,206,255)" fill-opacity="1" d="M 235 94 L 224 90 L 244 89 L 255 93 Z" stroke-linejoin="round"></path></g><g r="0" stroke="#7cb5ec" stroke-width="1"><path fill="#7cb5ec" d="M 194 250 L 214 248 L 214 248 L 194 250 Z" stroke-linejoin="round"></path><path fill="rgb(149,206,255)" fill-opacity="1" d="M 194 250 L 184 245 L 204 243 L 214 248 Z" stroke-linejoin="round"></path><path fill="rgb(99,156,211)" fill-opacity="1" d="M 194 250 L 184 245 L 184 245 L 194 250 Z" stroke-linejoin="round"></path></g><g r="0" stroke="#7cb5ec" stroke-width="1"><path fill="#7cb5ec" d="M 152 131 L 173 130 L 173 253 L 153 255 Z" stroke-linejoin="round"></path><path fill="rgb(99,156,211)" fill-opacity="1" d="M 152 131 L 142 127 L 143 249 L 153 255 Z" stroke-linejoin="round"></path><path fill="rgb(149,206,255)" fill-opacity="1" d="M 152 131 L 142 127 L 163 126 L 173 130 Z" stroke-linejoin="round"></path></g><g r="0" stroke="#7cb5ec" stroke-width="1"><path fill="#7cb5ec" d="M 66 170 L 88 168 L 89 262 L 68 264 Z" stroke-linejoin="round"></path><path fill="rgb(99,156,211)" fill-opacity="1" d="M 66 170 L 57 165 L 59 259 L 68 264 Z" stroke-linejoin="round"></path><path fill="rgb(149,206,255)" fill-opacity="1" d="M 66 170 L 57 165 L 79 163 L 88 168 Z" stroke-linejoin="round"></path></g><g r="0" stroke="#7cb5ec" stroke-width="1"><path fill="#7cb5ec" d="M 23 206 L 44 204 L 45 267 L 24 269 Z" stroke-linejoin="round"></path><path fill="rgb(99,156,211)" fill-opacity="1" d="M 23 206 L 14 201 L 15 264 L 24 269 Z" stroke-linejoin="round"></path><path fill="rgb(149,206,255)" fill-opacity="1" d="M 23 206 L 14 201 L 36 199 L 44 204 Z" stroke-linejoin="round"></path></g></g><g class="highcharts-markers" visibility="visible" transform="translate(75,75) scale(1 1)" clip-path="none"></g></g><text x="300" text-anchor="middle" class="highcharts-title" style="color:#333333;font-size:18px;fill:#333333;width:536px;" y="25"><tspan>3D chart with null values</tspan></text><text x="300" text-anchor="middle" class="highcharts-subtitle" style="color:#555555;fill:#555555;width:536px;" y="53"><tspan>Notice the difference between a 0 value and a null point</tspan></text><g class="highcharts-legend" transform="translate(270,364)"><g ><g><g class="highcharts-legend-item" transform="translate(8,3)"><text x="21" style="color:#333333;font-size:12px;font-weight:bold;cursor:pointer;fill:#333333;" text-anchor="start" y="15">Sales</text><rect x="0" y="4" width="16" height="12" fill="#7cb5ec"></rect></g></g></g></g><g class="highcharts-axis-labels highcharts-xaxis-labels" ><text x="110" text-anchor="middle" style="width:25px;color:#606060;cursor:default;font-size:11px;fill:#606060;" y="363" z="-59" opacity="1">Jan</text><text x="154" text-anchor="middle" style="width:25px;color:#606060;cursor:default;font-size:11px;fill:#606060;" y="358" z="-40" opacity="1">Feb</text><text x="197" text-anchor="middle" style="width:25px;color:#606060;cursor:default;font-size:11px;fill:#606060;" y="353" z="-22" opacity="1">Mar</text><text x="239" text-anchor="middle" style="width:25px;color:#606060;cursor:default;font-size:11px;fill:#606060;" y="348" z="-3" opacity="1">Apr</text><text x="280" text-anchor="middle" style="width:25px;color:#606060;cursor:default;font-size:11px;fill:#606060;" y="343" z="16" opacity="1">May</text><text x="320" text-anchor="middle" style="width:25px;color:#606060;cursor:default;font-size:11px;fill:#606060;" y="338" z="35" opacity="1">Jun</text><text x="359" text-anchor="middle" style="width:25px;color:#606060;cursor:default;font-size:11px;fill:#606060;" y="334" z="53" opacity="1">Jul</text><text x="398" text-anchor="middle" style="width:25px;color:#606060;cursor:default;font-size:11px;fill:#606060;" y="329" z="72" opacity="1">Aug</text><text x="435" text-anchor="middle" style="width:25px;color:#606060;cursor:default;font-size:11px;fill:#606060;" y="324" z="91" opacity="1">Sep</text><text x="472" text-anchor="middle" style="width:25px;color:#606060;cursor:default;font-size:11px;fill:#606060;" y="320" z="109" opacity="1">Oct</text></g><g class="highcharts-axis-labels highcharts-yaxis-labels" ><text x="502" text-anchor="start" style="width:55px;color:#606060;cursor:default;font-size:11px;fill:#606060;" y="301" z="122" opacity="1">0</text><text x="504" text-anchor="start" style="width:55px;color:#606060;cursor:default;font-size:11px;fill:#606060;" y="244" z="111" opacity="1">2</text><text x="505" text-anchor="start" style="width:55px;color:#606060;cursor:default;font-size:11px;fill:#606060;" y="187" z="100" opacity="1">4</text><text x="506" text-anchor="start" style="width:55px;color:#606060;cursor:default;font-size:11px;fill:#606060;" y="128" z="90" opacity="1">6</text><text x="508" text-anchor="start" style="width:55px;color:#606060;cursor:default;font-size:11px;fill:#606060;" y="69" z="79" opacity="1">8</text></g><g class="highcharts-tooltip" style="cursor:default;padding:0;white-space:nowrap;" transform="translate(0,-9999)"><path fill="none" d="M 3 0 L 13 0 C 16 0 16 0 16 3 L 16 13 C 16 16 16 16 13 16 L 3 16 C 0 16 0 16 0 13 L 0 3 C 0 0 0 0 3 0" stroke="black" stroke-opacity="0.049999999999999996" stroke-width="5" transform="translate(1, 1)"></path><path fill="none" d="M 3 0 L 13 0 C 16 0 16 0 16 3 L 16 13 C 16 16 16 16 13 16 L 3 16 C 0 16 0 16 0 13 L 0 3 C 0 0 0 0 3 0" stroke="black" stroke-opacity="0.09999999999999999" stroke-width="3" transform="translate(1, 1)"></path><path fill="none" d="M 3 0 L 13 0 C 16 0 16 0 16 3 L 16 13 C 16 16 16 16 13 16 L 3 16 C 0 16 0 16 0 13 L 0 3 C 0 0 0 0 3 0" stroke="black" stroke-opacity="0.15" stroke-width="1" transform="translate(1, 1)"></path><path fill="rgb(249, 249, 249)" fill-opacity=" .85" d="M 3 0 L 13 0 C 16 0 16 0 16 3 L 16 13 C 16 16 16 16 13 16 L 3 16 C 0 16 0 16 0 13 L 0 3 C 0 0 0 0 3 0"></path><text x="8" style="font-size:12px;color:#333333;fill:#333333;" y="21"></text></g><text x="590" text-anchor="end" style="cursor:pointer;color:#909090;font-size:9px;fill:#909090;" y="395">Highcharts.com</text></svg>
</div>
<section>
<canvas id="svg-canvas"></canvas>
</section>
根本不需要做任何编程。人们已经为此构建了一些在线应用程序,其中包括可定义的参数,例如尺寸、分辨率、输出格式等。
这是我为 svg->jpeg 找到的更好的在线图像转换应用程序之一。http://image.online-convert.com/convert-to-jpg