Serve images by mtime using Snap
I've started playing around with a security camera, simply storing images using motion for now.
This will take a snapshot any time motion is detected. To limit the disk usage, files are named based on the time of day only and the image contains the exact timestamp:
text_right %Y-%m-%d\n%T-%q
jpeg_filename %H/%M/%S_%q
I decided to create a simple webpage to allow me to review the images, latest on top. I can still find the latest image by using the mtime (modification time) on the filesystem.
The complete project code is hosted on github as a cabal project with the Snap web framework as a depedency. The complete code is only a single page long and does the following simple things.
Get the modification time of a file (as an integer, as we only use it for sorting):
getMTimeInteger :: FilePath -> IO Int
getMTimeInteger filepath = do
status <- getFileStatus filepath
let mtime = modificationTime status
return (fromEnum mtime)
and create a list of files with their modification time in a tuple list
listImagesWithCtime :: IO [(Int, FilePath)]
listImagesWithCtime = do
files <- find always (extension ==? ".jpg" ||? extension ==? ".png") imageHostingBasePath
mtimeFilenameTuplesOf files imageHostingBasePath
and then just write the list out as a JSON encoded list
imageIndexHandler :: Snap ()
imageIndexHandler = do
listing <- liftIO listImagesWithCtime
writeJSON (listing :: [(Int, FilePath)])
this allows for the front-end to load the files, sort by mtime, and finally lazy load them using the jquery-unveil plugin:
fileListing.sort();
fileListing.reverse();
$.each(fileListing, function addImage(idx, imageInformation){
var image = $("<img />"),
link = $("<a />"),
imageLocation = "images/" + imageInformation[1];
image.attr("src", "template.jpg");
image.attr("data-src", imageLocation);
link.attr("href", imageLocation);
link.append(image)
$("body").append(link);
});
$("img").unveil();
The end result? A long list of images, the bottom list of which does not load until you scroll down to see them:
If you want to give it a try, clone the repository and get to the point where you can call cabal run
. Happy hacking!