Skip to content
This repository has been archived by the owner on Jan 17, 2023. It is now read-only.

Commit

Permalink
use Content-Disposition for downloading images
Browse files Browse the repository at this point in the history
  • Loading branch information
dannycoates committed Apr 19, 2017
1 parent 3233e57 commit defb4b2
Show file tree
Hide file tree
Showing 5 changed files with 24 additions and 3 deletions.
1 change: 1 addition & 0 deletions package.json
Original file line number Diff line number Diff line change
Expand Up @@ -10,6 +10,7 @@
"atob": "2.0.3",
"aws-sdk": "2.40.0",
"btoa": "1.1.2",
"content-disposition": "0.5.2",
"convict": "3.0.0",
"cookies": "0.7.0",
"core-js": "2.4.1",
Expand Down
8 changes: 8 additions & 0 deletions server/src/pages/shot/model.js
Original file line number Diff line number Diff line change
@@ -1,9 +1,15 @@
const { createDownloadUrl } = require("../../proxy-url");
const { getGitRevision } = require("../../linker");
const MobileDetect = require('mobile-detect');

exports.createModel = function(req) {
let buildTime = require("../../build-time").string;
let isMobile = !!(new MobileDetect(req.headers['user-agent'])).mobile();
let downloadUrl = null;
let clip = req.shot.getClip(req.shot.clipNames()[0]);
if (clip) {
downloadUrl = createDownloadUrl(clip.image.url, req.shot.filename);
}
let serverPayload = {
title: req.shot.title,
staticLink: req.staticLink,
Expand All @@ -28,6 +34,7 @@ exports.createModel = function(req) {
cspNonce: req.cspNonce,
hashAnalytics: true,
userAgent: req.headers['user-agent'],
downloadUrl,
isMobile
};
let clientPayload = {
Expand All @@ -54,6 +61,7 @@ exports.createModel = function(req) {
defaultExpiration: req.config.defaultExpiration * 1000,
hashAnalytics: true,
userAgent: req.headers['user-agent'],
downloadUrl,
isMobile
};
if (serverPayload.expireTime !== null && Date.now() > serverPayload.expireTime) {
Expand Down
5 changes: 2 additions & 3 deletions server/src/pages/shot/view.js
Original file line number Diff line number Diff line change
Expand Up @@ -301,7 +301,6 @@ class Body extends React.Component {
let clip = this.props.shot.getClip(clipId);
clipUrl = clip.image.url;
}
let clipFilename = this.props.shot.filename;

let renderGetFirefox = this.props.userAgent && (this.props.userAgent + "").search(/firefox\/\d+/i) === -1;
let renderExtensionNotification = !(this.props.isExtInstalled || renderGetFirefox);
Expand All @@ -327,8 +326,8 @@ class Body extends React.Component {
</div>
<div className="more-shot-actions right">
{ trashOrFlagButton }
<a className="button secondary" href={ clipUrl } onClick={ this.onClickDownload.bind(this) }
title="Download the shot image" download={ clipFilename }>
<a className="button secondary" href={ this.props.downloadUrl } onClick={ this.onClickDownload.bind(this) }
title="Download the shot image">
<img src={ this.props.staticLink("/static/img/download.svg") } />
</a>
<ShareButton abTests={this.props.abTests} clipUrl={clipUrl} shot={shot} isOwner={this.props.isOwner} staticLink={this.props.staticLink} renderExtensionNotification={renderExtensionNotification} isExtInstalled={this.props.isExtInstalled} />
Expand Down
5 changes: 5 additions & 0 deletions server/src/proxy-url.js
Original file line number Diff line number Diff line change
Expand Up @@ -10,3 +10,8 @@ exports.createProxyUrl = function(req, url, hash) {
}
return proxy;
};

exports.createDownloadUrl = function(url, filename) {
const sig = dbschema.getKeygrip().sign(new Buffer(filename, 'utf8'));
return `${url}?download=${encodeURIComponent(filename)}&sig=${encodeURIComponent(sig)}`;
};
8 changes: 8 additions & 0 deletions server/src/server.js
Original file line number Diff line number Diff line change
Expand Up @@ -59,6 +59,7 @@ const {
const dbschema = require("./dbschema");
const express = require("express");
const bodyParser = require('body-parser');
const contentDisposition = require("content-disposition");
const csrf = require("csurf");
const morgan = require("morgan");
const linker = require("./linker");
Expand Down Expand Up @@ -771,6 +772,8 @@ app.post("/api/set-expiration", csrfProtection, function(req, res) {

app.get("/images/:imageid", function(req, res) {
let embedded = req.query.embedded;
let download = req.query.download;
let sig = req.query.sig;
Shot.getRawBytesForClip(
req.params.imageid
).then((obj) => {
Expand Down Expand Up @@ -805,6 +808,11 @@ app.get("/images/:imageid", function(req, res) {
}).send();
}
res.header("Content-Type", "image/png");
if (download) {
if (dbschema.getKeygrip().verify(new Buffer(download, 'utf8'), sig)) {
res.header("Content-Disposition", contentDisposition(download));
}
}
res.status(200);
res.send(obj.data);
}
Expand Down

0 comments on commit defb4b2

Please sign in to comment.