I was recently playing around with node a command line javascript interpreter based on the V8 javascript engine and wanted/needed to implement a file downloader class that properly handles HTTP 302 Redirects.
After a bit of yelling and screaming, I had a working implementation
Enter the Javascript
var url = require('url');
var http = require('http');
var fs = require('fs');
var write_file;
//what global variable do we have?
var complete = false;
var content_length = 0;
var downloaded_bytes = 0;
//create the downloader 'class'
var Downloader = function() {
//we will need to be able to set the remote file to download
this.set_remote_file = function(file) {
remote_file = file;
local_file = path.basename( remote_file );
}
//we want to set the local file to write to
this.set_local_file = function(file) {
local_file = file;
}
//run this fukker!
this.run = function() {
//start the download
this.download( remote_file, local_file, 0 );
}
this.download = function(remote, local, num) {
console.log( remote );
if ( num > 10 ) {
console.log( 'Too many redirects' );
}
//remember who we are
var self = this;
//set some default values
var redirect = false;
var new_remote = null;
var write_to_file = false;
var write_file_ready = false;
//parse the url of the remote file
var u = url.parse(remote);
//set the options for the 'get' from the remote file
var opts = {
host: u.hostname,
port: u.port,
path: u.pathname
};
//get the file
var request = http.get(opts, function(response ) {
switch(response.statusCode) {
case 200:
//this is good
//what is the content length?
content_length = response.headers['content-length'];
break;
case 302:
new_remote = response.headers.location;
self.download(new_remote, local_file, num+1 );
return;
break;
case 404:
console.log("File Not Found");
default:
//what the hell is default in this situation? 404?
request.abort();
return;
}
response.on('data', function(chunk) {
//are we supposed to be writing to file?
if(!write_file_ready) {
//set up the write file
write_file = fs.createWriteStream(local_file);
write_file_ready = true;
}
write_file.write(chunk);
downloaded_bytes+=chunk.length;
percent = parseInt( (downloaded_bytes/content_length)*100 );
console.log( percent );
});
response.on('end', function() {
complete = true;
write_file.end();
});
});
request.on('error', function(e) {
console.log("Got error: " + e.message);
});
}
}
exports.Downloader = Downloader;
To use this, one would need to create a script that utilizes the class. For example, suppose we wanted to download an episode of Rathole Radio we would need to write something along the lines of the following:
var dl = new Downloader.Downloader();
dl.set_remote_file('http://traffic.libsyn.com/ratholeradio/RR048_20_03_11.ogg');
dl.run();
Awesome 'Possum! Now quit reading and go do something nifty.
Recently, it became necessary for me to add a "share on facebook" feature to a project I am working on. A quick web search for "facebook share api" turned up the Facebook Share API that gives example code for for formatting a URL to share data on Facebook.
The ony problem the Facebook share code is that the code doesn't work. A custom title for what is being shared get's overridden by the title of the page at the given URL. A bit more digging with my internet shovel turned up some information about URL and Title being sent as part of an array and the URL would be sent as p[url] and the Title would be sent as p[title].
With that in mind, I wrote the following JavaScript function to format a URL and Title and share them on Facebook.
function shareOnFacebook(share_title,share_url) { //encode the share_title t=encodeURIComponent(share_title); //encode the share_url u=encodeURIComponent(share_url); //determine the target url to open target_url='http://www.facebook.com/sharer.php?s=100&p[title]='+t+'&p[url]='+u+'&t='+t; //open the target window.open(target_url,'share','toolbar=0,status=0,width=600,height=400'); }
Now quit reading, and go share some useless information of Facebook.
By the way, there is a 100 character limit for the title.
Update June 18 2010: Since both images and description have been asked for... The following function will allow the user to also set the image and description (which facebook call subject for some asinine reason)
function shareOnFacebook(title,url,desc,image) { t=encodeURIComponent(title); d=encodeURIComponent(desc); u=encodeURIComponent(url); i=encodeURIComponent(image); share_url='http://www.facebook.com/sharer.php'; share_url+='?s=100&p[title]='+t+'&p[summary]='+d+'&p[url]='+u; share_url+='&p[images][0]='+i; share_url+='&t='+t+'&e='+d; var myWindow = window.open(share_url, 'sharer', 'toolbar=0,status=0,width=626,height=436'); }
Well there you have it, I hope it works for you.
PS. If you are so inclined, you could buy me a cup of coffee. hint hint wink wink
All the tests for the meta Tags didn't work including the
<link rel="image_src" ...
With that solution, you can also integrate several thumbnails.
// Javascript for ShareOnFacebook Buttons
function shareOnFacebook(share_title,share_url,icon_url) {
//encode the share_title
t=encodeURIComponent(share_title);
//encode the share_url
u=encodeURIComponent(share_url);
//encode the icon_url
i=encodeURIComponent(icon_url);
//determine the target url to open
target_url='http://www.facebook.com/sharer.php?s=100&p[title]='+t+'&p[url]='+u+'&t='+t+'&p[images][0]='+i;
//open the target
window.open(target_url,'share','toolbar=0,status=0,width=600,height=400');
}
Thanks for posting the solution to use images. It is the visual aspect of sharing that really packs a punch
The Feature
Picture if you will.......
friend: you should fix your music page cuz it's crap
me: what?
friend: I went there and didn't know what to do
me: did you click the arrow pointing to the right that typically signifies "play"?
friend: what arrow?
me: whoa! what browser are you using?
friend: firefox
me:(pretending to be Morpheus) Show Me!
On my music page, I had a bunch of <audio> tags so that visitors to my site could hear me butcher various tunes that I have recorded. Unfortunately, the Firefox theme that my friend was using made Firefox's default audio player completely unusable.
Fine, I didn't like the look of the default player anyway!
What I Should Have Done
In hindsight, I should has just written some hardcoded javascript and CSS to make a nifty HTML5 audio player thing because I have decided that I really don't like working with JavaScript. Using a framework like GWT or Pyjamas that outputs JavaScript is fine, but hacking on JavaScript just isn't my thing. I suppose that it might have been easier if I had used a large JavaScript library like JQuery, but where is the hell is the fun in that? Oh well, maybe next time.
What I Did Do
Since my music page is created dynamically from information pulled from a database, I wanted a way to dynamically generate an HTML5 audio player based upon formatted text on a page; and well... that's what I did, and I named the project PagePlayer (boring, I know). By building it myself, I know exactly how the controls will look in various browsers, regardless of which theme the browser is using.
It may not be the best looking JavaScript generated music player thingy on the web, but it is my JavaScript generated music player thingy.
So fire up your HTML5 compatible browser and head over to my "music" page to check it out. Anyone interested in the code should visit the PagePlayer project page, where the HTML,JavaScript,CSS, images, and audio can be downloaded.
Now stop reading, and check your code for graceful degredation and IE6 compatibility.
I was wondering something : the variable local in " this.download = function(remote, local, num) {...}" is never used right ?
It really comes down to scope preference.