Reputation: 429
I am trying to process SVGs prior to sending them via Express.js. I have the following code:
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, " "));
});
});
Without setting the res.header()
, I can visit the route in the browser and it behaves as expected (scales to fit). Unfortunately, I can't embed them in an <img>
tag unless the header is set.
With res.header()
set, I can embed the image in an <img>
tag, but it doesn't behave as I would expect (static size).
Sending the file directly with res.sendFile(iconPath)
works correctly. I wondered if this was because the file needed to be sent as a binary which can be seen in res.send(new Buffer(svg, 'binary'))
but this had the same effect as res.send(svg)
.
The statement console.log(svg)
outputs the following code:
<?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>
I can think of a workaround which would be to save the file to a temp directory and using the res.sendFile(tempPath)
, but there has to be a better way...
Here is a sample of the response header:
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
Upvotes: 3
Views: 2427
Reputation: 429
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:
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 } );
Upvotes: 2