The Task
There is a blogger: its main content is pictures and photos, client wants to allow users to download today, this week and this month's pictures.
The Solution
The basic idea is to send a request to Blogger feed url, parse its json response to get all image links, then use JSZip and JQuery Deferred pattern to download all remote images.
Using GAE to Serve JavaScript Files
After download JSZip and JSZip-Utils, we need put them somewhere, so the blogger can load them. So we create one GAE application, and put them in the webapp/js/jszip folders.
We only want to load these scripts if the pageType is item: mean current page is a post page. So we add the following code under <b:includable id='post' var='post'>:
Add Download Links to Item Page
There is a blogger: its main content is pictures and photos, client wants to allow users to download today, this week and this month's pictures.
The Solution
The basic idea is to send a request to Blogger feed url, parse its json response to get all image links, then use JSZip and JQuery Deferred pattern to download all remote images.
Using GAE to Serve JavaScript Files
After download JSZip and JSZip-Utils, we need put them somewhere, so the blogger can load them. So we create one GAE application, and put them in the webapp/js/jszip folders.
We only want to load these scripts if the pageType is item: mean current page is a post page. So we add the following code under <b:includable id='post' var='post'>:
<b:includable id='post' var='post'> <b:if cond='data:blog.pageType == "item"'> <script src='//youapp.appspot.com/js/jszip/jszip.min.js'/> <script src='//youapp.appspot.com/js/jszip/jszip-utils.min.js'/> <script src='//youapp.appspot.com/js/jszip/FileSaver.js'/> </b:if>
Add Download Links to Item Page
<div class='blog-pager' id='blog-pager'> <b:if cond='data:blog.pageType == "item"'> <div class='blog-pager' id='blog-pager'> <div id='blog-pager-newer-link'> <a class='blog-pager-newer-link' href='' id='downloadToday'>Download Today's Images</a> </div> <div id='blog-pager-older-link'> <a class='blog-pager-newer-link' href='' id='downloadMonth'>Download This Month's Images</a> </div> <div id='blog-pager-home-link'> <a class='blog-pager-newer-link' href='' id='downloadWeek'>Download This Week's Images</a> </div> </div> </b:if> ... </div>
The Complete JavaScript Code
Using Blogger Feeds URL to Get Post in Range
Using JSZip and JQuery Deferred Pattern to Download Multiple Remote Images
<b:includable id='post' var='post'> <b:if cond='data:blog.pageType == "item"'> <script src='//lifelongprogrammertools.appspot.com/js/jszip/jszip.min.js'/> <script src='//lifelongprogrammertools.appspot.com/js/jszip/jszip-utils.min.js'/> <script src='//lifelongprogrammertools.appspot.com/js/jszip/FileSaver.js'/> <script> var dateHeader= '<data:post.dateHeader/>'; var parts = dateHeader.split('-'); var postDate = new Date(parts[0], parts[1]-1, parts[2]); console.log("postDate:" + postDate); //<![CDATA[ $(function($) { if(JSZip.support.blob) { $("#downloadToday").click(function (e) { getTodayAllImages(dateHeader); e.preventDefault(); return false; }); $("#downloadWeek").click(function (e) { getWeekAllImages(postDate); e.preventDefault(); return false; }); $("#downloadMonth").click(function (e) { getMonthAllImages(postDate); e.preventDefault(); return false; }); } }); function addToZip(zip, link, postUrl, i) { var deferred = $.Deferred(); JSZipUtils.getBinaryContent(link, function (err, data) { if(err) { alert("Problem happened when download image from " + postUrl + ", img link: " + link); console.error("Problem happened when download image from " + postUrl + ", img link: " + link); deferred.resolve(zip); // ignore this error: just logging // deferred.reject(zip); } else { zip.file("picture"+i+".jpg", data, {binary:true}); deferred.resolve(zip); } }); return deferred; } function parseImagesRsp(root){ var feed = root.feed; var parser = new DOMParser(); var zip = new JSZip(); var deferreds = []; for(var i=0; i<feed.entry.length; i++) { var e=feed.entry[i]; var doc = parser.parseFromString(e.content.$t, "text/html"); var img = doc.querySelector("img"); var pageUrl = e.link[2].href; if(!img) { console.error("No img tag in " + pageUrl); } else{ var imgLink = img.src; console.log("img link: " + imgLink); deferreds.push( addToZip(zip, imgLink, pageUrl, i) ); } } $.when.apply(window, deferreds).done(generateZip); } function generateZip(zip) { var content = zip.generate({type:"blob"}); // see FileSaver.js saveAs(content, "downloadImages.zip"); } function doDownload(startDate, endDate){ var script = document.createElement('script'); script.type = 'text/javascript'; script.src = '/feeds/posts/default?published-min=' + startDate + '&published-max='+endDate+'&alt=json-in-script&max-results=1000&callback=parseImagesRsp'; document.getElementsByTagName('head')[0].appendChild(script); } function getTodayAllImages(dateStr){ var startDate = dateStr + "T00:00:01", endDate = dateStr + "T23:59:59"; console.log("Download images from " + startDate + " to " + endDate); doDownload(startDate, endDate); return false; } function getMonthAllImages(dateObj){ var startDate = yymmdd(getFirstDayOfCurrentMonth(dateObj)) + "T00:00:01", endDate = yymmdd(getLastDayOfCurrentMonth(dateObj)) + "T23:59:59"; doDownload(startDate, endDate); return false; } function getWeekAllImages(dateObj){ var startDate = yymmdd(getMondayOfCurrentWeek(dateObj)) + "T00:00:01", endDate = yymmdd(getSundayOfCurrentWeek(dateObj)) + "T23:59:59"; doDownload(startDate, endDate); return false; } function yymmdd(dataObj){ var month = (dataObj.getMonth()+1); var monthStr = month<10? ('0' + month): month; var dateStr = dataObj.getDate()< 10? ('0' + dataObj.getDate()): dataObj.getDate(); return dataObj.getFullYear() + "-" + monthStr + "-" + dateStr; } function getMondayOfCurrentWeek(d) { var day = d.getDay(); return new Date(d.getFullYear(), d.getMonth(), d.getDate()-day + (day == 0 ? -6:1)); } function getSundayOfCurrentWeek(d) { var day = d.getDay(); return new Date(d.getFullYear(), d.getMonth(), d.getDate()-day + (day == 0 ? 0:7)); } function getFirstDayOfCurrentMonth(d){ return new Date(d.getFullYear(), d.getMonth(), 1); } function getLastDayOfCurrentMonth(d){ return new Date(d.getFullYear(), d.getMonth()+1, 0); } //]]> </script> </b:if>