|
|||||||||||||||||||||||
|
|||||||||||||||||||||||
|
Announcements
Chapters
Services
Feature Zones
|
Introduction
How a Segmented Download WorksDownloads can be segmented because both HTTP and FTP protocols allow the client to specify the start position of the stream. First, segment size = min( (file size / number of segments),
minimum allowed segment size )
With the segment size, Using the Code: MyDownloader APITo start a segmented download using the
// starts to listen to the event 'DownloadEnded' from DownloadManager
DownloadManager.Instance.DownloadEnded +=
new EventHandler<DownloaderEventArgs>(Instance_DownloadEnded);
// indicates that download should start immediately
bool startNow = true;
Downloader download = DownloadManager.Instance.Add(
"http://jogos.download.uol.com.br/videos/pc/thewitcher12.wmv",
@"c:\temp\thewitcher12.wmv",
3, // Three segments
startNow // Start download now
);
void Instance_DownloadEnded(object sender, DownloaderEventArgs e)
{
if (Settings.Default.ShowBallon &&
AppManager.Instance.Application.NotifyIcon.Visible)
{
// Display the XP Balloon
}
finally
{
DownloadManager.Instance.OnEndAddBatchDownloads();
}
AppManager.Instance.Application.NotifyIcon.ShowBalloonTip(
Settings.Default.BallonTimeout,
AppManager.Instance.Application.MainForm.Text,
String.Format("Download finished: {0}", e.Downloader.LocalFile),
ToolTipIcon.Info);
}
}
Protocol AbstractionOn previous versions of MyDownloader, the protocols support was implemented by classes that inhererited from For that reason, I have refactored the code and now all supported protocols (HTTP, FTP, HTTPS) are implemented by classes that implement To make it easier to retrieve the correct
Plug-in ArchitectureMany features from
Below, you can see how we load settings from the extension to populate the tree view: for (int i = 0; i < App.Instance.Extensions.Count; i++)
{
IExtension extension = App.Instance.Extensions[i];
IUIExtension uiExtension = extension.UIExtension;
Control[] options = uiExtension.CreateSettingsView();
TreeNode node = new TreeNode(extension.Name);
node.Tag = extension;
for (int j = 0; j < options.Length; j++)
{
TreeNode optioNd = new TreeNode(options[j].Text);
optioNd.Tag = options[j];
node.Nodes.Add(optioNd);
}
treeOptions.Nodes.Add(node);
}
The public class HttpFtpProtocolExtension: IExtension
{
#region IExtension Members
public string Name
{
get { return "HTTP/FTP"; }
}
public IUIExtension UIExtension
{
get { return new HttpFtpProtocolUIExtension(); }
}
public HttpFtpProtocolExtension()
{
ProtocolProviderFactory.RegisterProtocolHandler("http",
typeof(HttpProtocolProvider));
ProtocolProviderFactory.RegisterProtocolHandler("https",
typeof(HttpProtocolProvider));
ProtocolProviderFactory.RegisterProtocolHandler("ftp",
typeof(FtpProtocolProvider));
}
#endregion
}
When we think of an HTTP download, what are the settings that an HTTP downloader would require? Proxy is one of the answers. Many users are behind an HTTP proxy and connecting directly to an HTTP server is not allowed in most companies. So, to expose the settings for our public class HttpFtpProtocolUIExtension : IUIExtension
{
public System.Windows.Forms.Control[] CreateSettingsView()
{
// create the Proxy user control an return it.
return new Control[] { new Proxy() };
}
public void PersistSettings(System.Windows.Forms.Control[] settingsView)
{
...
}
...
}
The Web SpiderWeb Spider works over
When an download of an file is complete (download state is changed to DownloaderState.Ended), the spider checks if it's an HTML document (comparing the mime type) and then lookup for all references such hyperlinks, images, frames and iframes. The following code is executed to add all page references to the download list: ...
if (download.RemoteFileInfo.MimeType.IndexOf("text/html",
StringComparison.OrdinalIgnoreCase) < 0)
{
return;
}
...
try
{
DownloadManager.Instance.OnBeginAddBatchDownloads();
using (Stream htmlStream = File.OpenRead(localFile))
{
using (HtmlParser parser = new HtmlParser(htmlStream))
{
AddUrls(parser.GetHrefs(context.BaseLocation), UrlType.Href);
AddUrls(parser.GetImages(context.BaseLocation), UrlType.Img);
AddUrls(parser.GetFrames(context.BaseLocation), UrlType.Frame);
AddUrls(parser.GetIFrames(context.BaseLocation), UrlType.IFrame);
}
}
}
finally
{
DownloadManager.Instance.OnEndAddBatchDownloads();
}
Video Downloads from YouTube, Google Video (and etc) with ConversionLike many Setting this property, when The first step is register the Video protocol providers on public VideoDownloadExtension()
{
handlers = new List<VideoDownloadHandler>();
handlers.Add(new VideoDownloadHandler(YouTubeDownloader.SiteName,
YouTubeDownloader.UrlPattern, typeof(YouTubeDownloader)));
handlers.Add(new VideoDownloadHandler(GoogleVideoDownloader.SiteName,
GoogleVideoDownloader.UrlPattern, typeof(GoogleVideoDownloader)));
// ... register other sites here ...
}
After registering, we need to discover which video handler we need to use and also, set the correct protocol provider on the
VideoDownloadExtension extension;
...
extension = (VideoDownloadExtension)App.Instance.GetExtensionByType(
typeof(VideoDownloadExtension));
...
handler = extension.GetHandlerByURL(txtURL.Text);
...
ResourceLocation rl = ResourceLocation.FromURL(txtURL.Text);
rl.ProtocolProviderType = handler.Type.AssemblyQualifiedName;
Basically, all video site handlers only need to parse the HTML page and return the URL of the FLV. This process have three main steps:
All common things are on public class YouTubeDownloader: BaseVideoDownloader
{
public const string SiteName = "You Tube";
//http://www.youtube.com/watch?v=5zOevLN3Tic
public const string UrlPattern =
@"(?:[Yy][Oo][Uu][Tt][Uu]
After downloadeding, the video can be converted to MPEG, AVI or MP3 (audio only), this process in done using an external open source tool: ffmpeg. This tool, which is a command line tool, is called by Selecting Files inside a Remote ZIP FileThis is another very cool feature of MyDownloder. Sometimes, you need to download an big ZIP file just because you want a single file inside the ZIP, on New Download window, if user checks the option "Choose files inside ZIP", The feature is based on the article Extracting files from a remote ZIP archive and the updated version by Unruled Boy (see comments on the end of the article). Below we can the how New Download window displays the ZIP file and allow user to choose the files inside ZIP:
Auto-DownloadsThe Auto-Downloads is activated (or deactivated) through the "two arrows" button in The maximum number of downloads is configured in the "Options" dialog. Another nice thing is that the user is able to choose at which times the "Auto-Downloads" will work and is also possible to limit the bandwidth usage at specific times. This is done easily by selecting the "time grid":
The Auto-Downloads, works using events (DownloadAdded, DownloadEnded) from using (DownloadManager.Instance.LockDownloadList(false))
{
int count = GetActiveJobsCount();
int maxJobs = Settings.Default.MaxJobs;
if (count < maxJobs)
{
for (int i = 0;
i < DownloadManager.Instance.Downloads.Count && (count < maxJobs);
i++)
{
if (DownloadManager.Instance.Downloads[i].State !=
DownloaderState.Ended &&
! DownloadManager.Instance.Downloads[i].IsWorking())
{
DownloadManager.Instance.Downloads[i].Start();
count ++;
}
}
}
}
Internet Explorer IntegrationBrowser integration is a critical feature for any download manager. This new version of
Below we can see the IE displaying an empty page and perceive that the download button is disabled, the second image shows IE displaying a YouTube video and the download button became enabled:
To enable the video download button, we need to listen to the void AfterNavigate(object iDisp, ref object URL)
{
SHDocVw.WebBrowser IEDocument = GetIEDocument();
btnDownload.Enabled = videoSites.IsVideoSite(IEDocument.LocationURL);
}
To replace the IE download window (only when Alt is pressed), the void FileDownload(bool ActiveDocument, ref bool Cancel)
{
if (!ActiveDocument)
{
if ((Control.ModifierKeys & Keys.Alt) == Keys.Alt)
{
Cancel = true;
if ((DateTime.Now - lastDownload).TotalSeconds >= 1.9)
{
ThreadPool.QueueUserWorkItem(
delegate(object state)
{
DownloadURL(lastUrl);
});
lastDownload = DateTime.Now;
}
}
}
}
Import URLs from FilesOther new feature of All URLs that were found in the file will be added to the download list. "Import URLs from files" window also have a shortcut to enable the "Auto-downloads", and to setup the maximum number of simultaneous downloads.
Future IdeasThis kind of project is "infinite," so below I have listed some ideas for future implementations. As any open source project, it would be very nice if you wish to contribute.
I hope you enjoyed the code! If you have any questions or feedback, feel free to contact me. | ||||||||||||||||||||||