使用Express.js提供纯文本SVG(与Cheerio.js相关的解决方案)

时间:2016-10-20 00:15:50

标签: html css node.js express svg

我试图在通过Express.js发送之前处理SVG。我有以下代码:

app.get("/iconic/styles/:style/:base/:icon", function (req, res) {
    var style = req.params.style;
    var base = req.params.base;
    var icon = req.params.icon;

    var iconPath = path.join(iconFolderRoot, style, icon);

    svgProcessor(iconPath, base).then(function (svg) {
        //console.log(svg);  // SO: See the example output posted below

        res.header("Content-Type","image/svg+xml");

        //res.send(new Buffer(svg, 'binary')); // No difference

        res.send(svg);
    }).catch(function (err) {
        res.status(404).send("Error" + JSON.stringify(err, null, "  "));
    });
});

如果不设置res.header(),我可以在浏览器中访问该路径,它的行为符合预期(缩放以适应)。遗憾的是,除非设置了标头,否则我无法将它们嵌入<img>标记中。

设置res.header()后,我可以将图片嵌入到<img>标记中,但它的行为与我预期的一样(静态大小)。

直接使用res.sendFile(iconPath)发送文件可以正常工作。我想知道这是否是因为文件需要作为二进制文件发送,可以在res.send(new Buffer(svg, 'binary'))中看到,但这与res.send(svg)具有相同的效果。

语句console.log(svg)输出以下代码:

<?xml version="1.0" encoding="utf-8"?>
<!-- Generator: Adobe Illustrator 19.2.1, SVG Export Plug-In . SVG Version: 6.00 Build 0)  -->
<svg version="1.1" id="Layer_1" xmlns="http://www.w3.org/2000/svg" xmlns:xlink="http://www.w3.org/1999/xlink" x="0px" y="0px" viewbox="0 0 128 128" style="enable-background:new 0 0 128 128;" xml:space="preserve">
<style type="text/css">
        .st0{fill:#49C5B1;}
</style>
<title>Icons_TEST</title>
<g id="Example">
        <path {{{REMOVED FOR STACKOVERFLOW POST}}}/>
</g>
</svg>

我可以想到一个解决方法,即将文件保存到临时目录并使用res.sendFile(tempPath),但必须有更好的方法......

以下是响应标头的示例:

HTTP/1.1 200 OK
X-Powered-By: Express
Content-Type: image/svg+xml
Date: Thu, 20 Oct 2016 00:51:18 GMT
Connection: keep-alive
Content-Length: 3577

1 个答案:

答案 0 :(得分:1)

After posing this question in the Express github page, a user indicated that they were curious about the svgProcessor as a potential problem. Believing that the problem was related to the way it was being served, I tried to eliminate this as a potential cause by rendering the svg directly with res.render(fs.readFileSync(iconPath)). To my surprise, this actually rendered as expected.

I stared at the output from the svgProcessor for a long period of time and couldn't see the difference so I ran it through an online diffing tool and it showed the following:

enter image description here

Even with the answer right in front of me, I still didn't see what the problem was. Then I realized, the B in viewBox was being lower-cased! This was due to a package called Cheerio (which I was using for traversing the svg nodes) normalizing the attributes.

Solution: var $ = cheerio.load(svg, { xmlMode: true } );