php - 用 php 下载 svg
问题描述
我想为 svg 创建一个 php 下载。Rn 我正在创建一个 svg 段,现在我想将该段放入下载中,但不知道如何。
有下载部分(download.php)及其从 index.php 加载代码
$file = include('index.php');
header('Content-Disposition: attachment; filename="segment.svg"');
header('Content-Type: image/svg');
header('Content-Length: ' . strlen($file));
header('Connection: close');
echo $file;
exit();
有index.php
<body>
<div class="container">
<form action="index.php" method="get">
<label for="segments">Segmente</label><br/>
<input type="number" id="segments" name="segment">
<input type="submit" value="Absenden" name="submit">
</form>
<?php
$getSegment = $_GET['segment'];
// I deleted some code here
<svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" id="svg">
<?php for ($i = 0; $i < 1; $i++): ?>
<?php
$start_angle = $segment_arc * $i;
$end_angle = $segment_arc * ($i + 1);
?>
<path fill="#red" stroke-width="0" d="<?php echo $generate_arc($start_angle, $end_angle) ?>" />
<?php endfor ?>
</svg>
</div>
<div class="container">
<button class="btn btn-primary" onclick="location.href='download.php'">Download</button>
</div>
</body>
<?php
}
echo segment_circle($getSegment);
} else if (!isset($getSegment) || empty($getSegment)) {
echo 'Bitte trag eine Segmentanzahl ein!';
}
解决方案
这是我没有 PHP 代码的 JavaScript 解决方案,我在对您的问题的评论中快速解释了这一点。
为什么要在 JS 中这样做?
JS解决方案的优势
没有 HTTP 调用,因此服务器上没有处理。这将节省 CPU 并为最终用户更快。
您的页面可能包含多个 SVG 图像,您不需要在服务器端处理这种情况。我的 JS 解决方案处理多个 SVG 图像和下载按钮。
顺便说一句,SVG 本身可以直接用 JS 生成,而不是用 PHP 生成。
JS方案的缺点
- 如果浏览器没有启用 JS,那么它将无法工作。但这可能非常罕见。
您总是可以选择 PHP 解决方案。我们会让你自己做。无论如何,我们还没有得到您的 PHP 代码。我也不明白你的 PHP 循环for ($i = 0; $i < 1; $i++):
,这意味着你只做一次,所以循环不是必需的。
JS 解决方案的工作原理
您在 SVG 图像和下载按钮周围添加一些 HTML 标记。如果您的页面中有多个,这会将它们分开。我还添加了一个
data-filename
属性,以便您可以轻松设置不同的文件名。如果未设置该属性,则它会下降到在常量中设置的默认值。JavaScript 代码将在下载按钮上添加一个单击事件处理程序。当单击触发此选项时,它将执行以下操作:
- 创建一个
<a>
元素。 - 将 SVG 代码放入
href
属性中。 - 将
download
属性设置为具有良好的文件名。 - 使其
<a>
不可见并将其添加到 DOM。 - 在其上模拟单击事件以启动下载。
- 从 DOM 中删除
<a>
元素,因为我们不再需要它。
- 创建一个
代码和工作演示
我在这里创建了一个 Codepen.io:Download a SVG with JS
这是用于阅读的复制粘贴解决方案。
注意:它不适用于最新版本的Chrome、Edge(可能是Safari)上的 Stackoverflow 片段,因为出于安全原因,iframe 中禁用了下载。
但它可以在您的网站上运行,因为它没有嵌入到<iframe>
.
// An SVG file has an XML header which you don't use if the SVG is in the HTML document.
// As we want to generate a file, we'll add it before the <svg> tag to be compliant.
const SVG_XML_HEADER = '<?xml version="1.0" encoding="UTF-8" standalone="no"?>';
// The default SVG filename in case the data-filename attribute isn't set.
const DEFAULT_SVG_FILENAME = 'cake.svg';
// Get all the SVG containers of the page.
let svg_containers = document.querySelectorAll('.svg-container');
// For each SVG container, we'll bind the click event to the button to download the SVG.
svg_containers.forEach(function (svg_container, i) {
let svg_image = svg_container.querySelector('.svg-image');
// Let's get an optional filename from the data-filename attribute.
let svg_filename = svg_image.getAttribute('data-filename') || DEFAULT_SVG_FILENAME;
// The SVG code is the XML header and the trimmed inner HTML of the <div class="svg-image">.
let svg_code = SVG_XML_HEADER + "\n" + svg_image.innerHTML.trim();
// Now we want to bind the click event to the button so that it can download the SVG code above.
// First let's get the <button>.
let download_button = svg_container.querySelector('button');
// Add the "click" handler on it.
download_button.addEventListener('click', function (event) {
// To do the "download" we need to do create a <a> element and click on it:
// Create the <a> element.
var a = document.createElement('a');
// Set it's href to have the SVG content directly in the URL.
a.setAttribute('href', 'data:image/svg+xml;charset=utf-8,' + encodeURIComponent(svg_code));
// Set the filename for the "save as" dialog box.
a.setAttribute('download', svg_filename);
// Don't display this link in the HTML page.
a.style.display = 'none';
// Put it in the HTML page so that we can click on it.
document.body.appendChild(a);
// This click will generate the download.
a.click();
// Remove the created link from the HTML page.
document.body.removeChild(a);
});
});
html, body {
margin: 0;
padding: 0;
}
.grid {
display: flex;
flex-wrap: wrap;
}
.svg-container {
text-align: center;
margin: 1em;
padding: 1em;
border: 1px solid silver;
}
<div class="grid">
<div class="svg-container">
<div class="svg-image" data-filename="charkle_cake.svg">
<svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" id="svg">
<path d="M100,100 h-90 a90,90 0 1,0 90,-90 z"
fill="gray" stroke="black" stroke-width="2" />
</svg>
</div>
<button class="btn btn-primary">Download</button>
</div>
<div class="svg-container">
<div class="svg-image" data-filename="strawberry_cake.svg">
<svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" id="svg">
<path d="M100,100 h-90 a90,90 0 1,0 90,-90 z"
fill="#fee" stroke="red" stroke-width="2"
transform="rotate(225, 100, 100)" />
</svg>
</div>
<button class="btn btn-primary">Download</button>
</div>
<div class="svg-container">
<div class="svg-image">
<svg width="200" height="200" viewBox="0 0 200 200" xmlns="http://www.w3.org/2000/svg" id="svg">
<path d="M100,100 h-90 a90,90 0 1,0 90,-90 z"
fill="#efe" stroke="green" stroke-width="2"
transform="rotate(135, 100, 100)" />
</svg>
</div>
<button class="btn btn-primary">Download</button>
</div>
</div>
推荐阅读
- bash - Talend Sqoop 将我的自由形式查询拆分为不同的变量
- docker - docker 备份是否包含来自 .env 文件的环境变量?
- flutter - 参数类型'Map
' 不能分配给参数类型 'Map ' 更新 SDK 版本后 - php - 如何在php中使用来自foreach循环的数据创建一个json数组
- html - 如何在 express.js 应用程序中实现 X-Content-Type-Options 标头
- java - AWS Cognito:连接池关闭@Bean
- sql - 如何在选择查询中使用 iff 将来自数据源的 N/A 值替换为雪花上的时间戳字段
- assembly - 装配中未使用的数据需要防止分段错误
- mysql - 如何使用过程创建循环并提取结果
- html - 画廊设置-boostrap 4 模型