Article Image
read

While looking for a way to automate my screenshot sharing, I recently stumbled across UpShot.it. UpShot is a small utility for OSX that attaches itself to your Dropbox Public folder and uploads screenshots as you take them. The URL for the uploaded screenshot is copied to your system’s clipboard for easy sharing. It’s a great tool, especially if your throwing screenshots back and forth frequently on a team.

One particularly cool feature of UpShot is its ability to mask the long Dropbox URLs behind custom domains. The documentation for UpShot explains how to set up a custom .htaccess file on your server to redirect traffic from the domain to the Dropbox URL. However, this method suffers one downfall: when a user navigates to your custom URL, your server sends a 302, the user is redirected to the Dropbox URL, and the shortened URL is lost.

There are a couple ways around this problem, some even officially mentioned. I investigated two of my own solutions: enabling mod_proxy, or reading the image through a script. Since my custom URL is pointing to hosting on a shared server, I don’t have the ability to turn Apache packages on or off. This leaves writing a script.

For compatibility’s sake, I’ve opted to write this script in PHP. Before diving into that, we’ll need to set up a new .htaccess file. The server needs to redirect all requests for screenshots to our custom PHP script, screenshot.php:

.htaccess

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteRule ^/?$ http://amussey.com [L]
RewriteRule ^([A-Za-z0-9.\-]+)$ screenshot.php?file=$1 [L,QSA]

Obviously, you’ll want to replace http://amussey.com with your own domain name. This line isn’t necessary, but serves as an easy redirect if someone decides to go snooping around.

screenshot.php

<?php
// Be sure to fill in your public Dropbox ID!
// You can get this from the UpShot preferences pane.
define(DROPBOX_URL, "https://dl.dropboxusercontent.com/u/[ Your Public Dropbox ID ]/Screenshots/");

// Treat all warnings as exceptions.
function exception_error_handler($errno, $errstr, $errfile, $errline ) {
    throw new ErrorException($errstr, $errno, 0, $errfile, $errline);
}
set_error_handler("exception_error_handler");

// Check to make sure the request is actually for an image file.
$file_extension = strtolower(substr($_GET["file"], -4));
if (($file_extension != ".png" && $file_extension != ".jpg") || strlen($_GET["file"]) != 8) {
    http_response_code(400);
    die("Not a valid image.");
}

// Let's get that screenshot!
$url = DROPBOX_URL.$_GET["file"];

try {
    return_image($url);
} catch (Exception $e) {
    // Failed to find the image.  Try again.
    sleep(3);
    try {
        return_image($url);
    } catch (Exception $e) {
        http_response_code(404);
        die("Image not found.");
    }
}

function return_image($url) {
    $imginfo = getimagesize($url);
    header("Content-type: ".$imginfo['mime']);
    readfile($url);
}
?>

Of course, there are some drawbacks to this method. Like the Google App Engine (dropbprox) method, this solution uses 2x the bandwidth (fetching the image from Dropbox, and serving the image again from the PHP script) and increases latency. However, some of the increased latency is built in to this script and designed to improve performance; I found that the split second it took to upload the image to Dropbox was often just long enough to open the link and see a 404. The above script has been designed so that, if the first fetch of the image fails, it will retry in 3 seconds before 404ing.


Now that we have this script, why not take it one step further and add in analytics? (Note: Complete version of both of these files can be found on github.)

.htaccess

RewriteEngine On
RewriteCond %{REQUEST_FILENAME} !-f
RewriteCond %{REQUEST_FILENAME} !-d
RewriteRule ^/?$ http://amussey.com [L]
RewriteRule ^([A-Za-z0-9.\-]+)$ index.php?file=$1 [L,QSA]

screenshot.php

<?php
// Be sure to fill in your public Dropbox ID!
// You can get this from the UpShot preferences pane.
define(DROPBOX_URL, "https://dl.dropboxusercontent.com/u/[ Your Public Dropbox ID ]/Screenshots/");
define("ANALYTICS", true);
define("ANALYTICS_JSON", "dashboard/analytics.json");

// ... Inserted after $url = DROPBOX_URL.$_GET["file"]; ...

if (ANALYTICS) {
    $analytics_json = json_decode(file_get_contents(ANALYTICS_JSON), true);
    if (!isset($analytics_json[$_GET["file"]])) {
        $analytics_json[$_GET["file"]] = 0;
    }
    $analytics_json[$_GET["file"]]++;
    file_put_contents(ANALYTICS_JSON, json_encode($analytics_json));
}

// ... The rest of the PHP script ...
?>

These lines will write hits to an analytics.json file inside of a dashboard subdirectory. To review those hits, grab this dashboard.php file and copy it into the dashboard subdirectory as index.php.

Now if we want to see what files have been hit, we can just go to http://[My Custom Domain]/dashboard. It may be good to take an extra couple steps and set up some basic authentication on this folder so it’s not publicly accessible.

That’s all there is to it! Enjoy your shortened links!

Blog Logo

Andrew Mussey


Published

Image

Andrew Mussey

Software Developer at Samba TV, independent videographer, hobbyist DJ, & a Virginia Tech Hokie.

Back to Overview