using System;
using System.Collections.Generic;
using System.ComponentModel;
using System.Data;
using System.Drawing;
using System.Text;
using System.Windows.Forms;
using System.Net;
using System.Text.RegularExpressions;
using System.IO;
using System.Threading;
using System.Xml; namespace DownloadSVN
{ /// <summary>
/// SVN 2016-05-13
/// Geovin Du edit
/// </summary>
public partial class MainForm : Form
{
ManualResetEvent _waitingForStop;
ManualResetEvent _finishedReadingTree;
List<FileDownloadData> _filesToDownload;
Thread _readingThread;
String _selectedSourceType; public MainForm()
{
InitializeComponent(); this.comboBoxSourceType.SelectedIndex = 0;
} private void buttonBrowseTargetFolder_Click(object sender, EventArgs e)
{
using (FolderBrowserDialog fbd = new FolderBrowserDialog())
{
if (fbd.ShowDialog() == DialogResult.OK)
this.textBoxTargetFolder.Text = fbd.SelectedPath;
}
} private void buttonGo_Click(object sender, EventArgs e)
{
if (_readingThread == null)
{
_selectedSourceType = this.comboBoxSourceType.Text; Thread t = new Thread(new ThreadStart(Run));
t.Start();
_readingThread = t;
SetButtonGoText("Stop");
}
else
{
Stop();
}
} void Run()
{
// Start downloading threads
_finishedReadingTree = new ManualResetEvent(false);
_waitingForStop = new ManualResetEvent(false);
_filesToDownload = new List<FileDownloadData>(); List<Thread> downloadThreads = new List<Thread>();
for (int i = 0; i < 5; i++)
{
Thread t = new Thread(new ThreadStart(DownloadFilesThread));
t.Start();
downloadThreads.Add(t);
} try
{
if ((this.textBoxTargetFolder.Text != "") && (this.textBoxSourceSvnUrl.Text != ""))
{
string url = this.textBoxSourceSvnUrl.Text; if (_selectedSourceType == "GIT")
RunSvn(this.textBoxTargetFolder.Text, this.textBoxSourceSvnUrl.Text, RepositoryType.GIT);
else // "SVN"
RunSvn(this.textBoxTargetFolder.Text, this.textBoxSourceSvnUrl.Text, RepositoryType.SVN);
}
else
WriteToScreen("Parameters not set.");
}
catch (Exception ex)
{
WriteToScreen("Failed: " + ex);
lock (_filesToDownload)
{
_filesToDownload.Clear();
}
}
finally
{
_finishedReadingTree.Set();
} // Wait for downloading threads
WriteToScreen("Waiting for file downloading threads to finish");
for (int i = 0; i < downloadThreads.Count; i++)
downloadThreads[i].Join(); WriteToScreen("Done.");
MessageBox.Show("Done", "Done");
_readingThread = null; SetButtonGoText("Start");
} delegate void SetButtonGoTextDelegate(string text);
/// <summary>
///
/// </summary>
/// <param name="text"></param>
void SetButtonGoText(string text)
{
if (InvokeRequired == true)
{
this.Invoke(new SetButtonGoTextDelegate(SetButtonGoText), text);
return;
} buttonGo.Text = text;
}
/// <summary>
///
/// </summary>
void DownloadFilesThread()
{
while (true)
{
FileDownloadData fileDownloadData = null;
lock (_filesToDownload)
{
if (_filesToDownload.Count > 0)
{
fileDownloadData = _filesToDownload[0];
_filesToDownload.RemoveAt(0);
}
} if ((fileDownloadData == null) && (_finishedReadingTree.WaitOne(0, false) == true))
return; if (fileDownloadData != null)
{
bool retry = true;
while (retry == true)
{
if (_waitingForStop.WaitOne(0, false) == true)
return; try
{
DownloadFile(fileDownloadData.Url, fileDownloadData.FileName);
retry = false;
}
catch (Exception ex)
{
WriteToScreen("Failed to download: " + ex.Message);
}
}
}
else
{
Thread.Sleep(100);
}
}
}
/// <summary>
///
/// </summary>
public enum RepositoryType
{
SVN,
GIT
}
/// <summary>
///
/// </summary>
/// <param name="baseFolder"></param>
/// <param name="baseUrl"></param>
/// <param name="repositoryType"></param>
void RunSvn(string baseFolder, string baseUrl, RepositoryType repositoryType)
{
if (repositoryType == RepositoryType.SVN)
{
if (baseUrl.EndsWith("/") == false)
baseUrl += "/";
} if (baseFolder.EndsWith("\\") == false)
baseFolder += "\\"; List<FolderLinkData> urls = new List<FolderLinkData>();
urls.Add(new FolderLinkData(baseUrl, "")); while (urls.Count > 0)
{
if (_waitingForStop.WaitOne(0, false) == true)
{
WriteToScreen("Stopping...");
lock (_filesToDownload)
{
_filesToDownload.Clear();
}
break;
} FolderLinkData targetUrlData = urls[0];
string targetUrl = targetUrlData.Url;
urls.RemoveAt(0); // Create the folder
string relative;
if (targetUrlData.RelativePath == null)
relative = targetUrl.Substring(baseUrl.Length);
else
relative = targetUrlData.RelativePath; relative = relative.Replace("/", "\\");
string targetFolder = Path.Combine(baseFolder, relative);
if (Directory.Exists(targetFolder) == false)
Directory.CreateDirectory(targetFolder); // Download target page
string page = null;
bool retry = true;
while (retry == true)
{
if (_waitingForStop.WaitOne(0, false) == true)
return; try
{
page = DownloadUrl(targetUrl);
retry = false;
}
catch (Exception ex)
{
WriteToScreen("Failed to download: " + ex.Message);
}
} if (repositoryType == RepositoryType.SVN)
{
List<string> links = ParseLinks(page); foreach (string link in links)
{
string linkFullUrl = targetUrl + link;
if (linkFullUrl.EndsWith("/") == true)
{
urls.Add(new FolderLinkData(linkFullUrl, null));
}
else // file - download
{
string fileName = targetFolder + link;
lock (_filesToDownload)
{
_filesToDownload.Add(new FileDownloadData(linkFullUrl, fileName));
}
}
}
}
else if (repositoryType == RepositoryType.GIT)
{
List<PageLink> links = ParseGitLinks(page);
int pos = targetUrl.IndexOf("/?");
string serverUrl = targetUrl.Substring(0, pos); foreach (PageLink link in links)
{
string linkFullUrl = serverUrl + link.Url;
if (link.IsFolder == true)
urls.Add(new FolderLinkData(linkFullUrl, targetUrlData.RelativePath + link.Name + "\\"));
else
{
string fileName = targetFolder + link.Name; lock (_filesToDownload)
{
_filesToDownload.Add(new FileDownloadData(linkFullUrl, fileName));
}
}
}
}
}
}
/// <summary>
///
/// </summary>
/// <param name="page"></param>
/// <returns></returns>
List<string> ParseLinks(string page)
{
try
{
return ParseLinksFromXml(page);
}
catch
{
return ParseLinksFromHtml(page);
}
}
/// <summary>
///
/// </summary>
/// <param name="page"></param>
/// <returns></returns>
List<string> ParseLinksFromXml(string page)
{
List<string> list = new List<string>(); XmlDocument doc = new XmlDocument();
doc.LoadXml(page); XmlNode svnNode = doc.SelectSingleNode("/svn");
if (svnNode == null)
throw new Exception("Not a valid SVN xml"); foreach (XmlNode node in doc.SelectNodes("/svn/index/dir"))
{
string dir = node.Attributes["href"].Value;
list.Add(dir);
} foreach (XmlNode node in doc.SelectNodes("/svn/index/file"))
{
string file = node.Attributes["href"].Value;
list.Add(file);
} return list;
}
/// <summary>
///
/// </summary>
/// <param name="page"></param>
/// <returns></returns>
List<string> ParseLinksFromHtml(string page)
{
List<string> links = new List<string>();
string listArea = null; // Find list area: <ul> ... </ul>
int pos = page.IndexOf("<ul>");
if (pos >= 0)
{
int lastPos = page.IndexOf("</ul>", pos);
if (lastPos >= 0)
listArea = page.Substring(pos + 4, lastPos - (pos + 4));
} if (listArea != null)
{
string[] lines = listArea.Split('\n');
string linePattern = "<a [^>]*>([^<]*)<";
for (int i = 0; i < lines.Length; i++)
{
Match match = Regex.Match(lines[i], linePattern);
if (match.Success == true)
{
string linkRelUrl = match.Groups[1].Value;
if (linkRelUrl != "..")
links.Add(linkRelUrl);
}
}
} return links;
}
/// <summary>
///
/// </summary>
/// <param name="page"></param>
/// <returns></returns>
List<PageLink> ParseGitLinks(string page)
{
List<PageLink> links = new List<PageLink>(); string dataStartMarker = "<td class=\"mode\">";
string nameMarker = "hb=HEAD\">"; using (StringReader sr = new StringReader(page))
{
string line;
while ((line = sr.ReadLine()) != null)
{
if (line.StartsWith(dataStartMarker) == false)
continue; bool isFolder = false;
if (line[dataStartMarker.Length] == 'd')
isFolder = true; line = sr.ReadLine(); // Get name
int pos = line.IndexOf(nameMarker);
int endPos = line.IndexOf("<", pos);
pos += nameMarker.Length; string name = line.Substring(pos, endPos - pos); if ((name == "..") || (name == "."))
continue; // Get URL
pos = line.IndexOf("href=\"");
endPos = line.IndexOf("\">", pos);
pos += "href=\"".Length;
string url = line.Substring(pos, endPos - pos);
if (isFolder == false)
{
url = url.Replace(";a=blob;", ";a=blob_plain;"); pos = url.IndexOf(";h=");
url = url.Substring(0, pos);
url = url + ";hb=HEAD";
} if (url.Contains(";a=tree;"))
isFolder = true; links.Add(new PageLink(name, url, isFolder));
}
} return links;
} #region Download helper functions
/// <summary>
///
/// </summary>
/// <param name="url"></param>
/// <param name="fileName"></param>
void DownloadFile(string url, string fileName)
{
WriteToScreen("Downloading File: " + url); WebRequest webRequest = WebRequest.Create(url);
webRequest.ContentType = "text/html; charset=utf-8"; //考虑乱码问题
webRequest.Timeout = 50000;
WebResponse webResponse = null;
Stream responseStream = null;
try
{
webResponse = webRequest.GetResponse();
responseStream = webResponse.GetResponseStream();
// string page = new StreamReader(responseStream, Encoding.UTF8, true).ReadToEnd();
using (FileStream fs = new FileStream(fileName, FileMode.Create))
{
byte[] buffer = new byte[1024];
int readSize;
while ((readSize = responseStream.Read(buffer, 0, buffer.Length)) > 0)
{
fs.Write(buffer, 0, readSize);
}
}
}
finally
{
if (responseStream != null)
responseStream.Close(); if (webResponse != null)
webResponse.Close();
}
}
/// <summary>
///
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
string DownloadUrl(string url)
{
WriteToScreen("Downloading: " + url);
using (WebClient client = new WebClient())
{
client.Encoding = System.Text.Encoding.UTF8; //GetEncoding("utf-8"); //考虑乱码问题
string data = client.DownloadString(url); return data;
}
}
#endregion delegate void WriteToScreenDelegate(string str);
/// <summary>
///
/// </summary>
/// <param name="str"></param>
void WriteToScreen(string str)
{
if (this.InvokeRequired)
{
this.Invoke(new WriteToScreenDelegate(WriteToScreen), str);
return;
} this.richTextBox1.AppendText(str + "\n");
this.richTextBox1.ScrollToCaret();
} private void buttonClose_Click(object sender, EventArgs e)
{
this.Close();
} private void Stop()
{
_waitingForStop.Set();
} private void MainForm_FormClosing(object sender, FormClosingEventArgs e)
{
if (_readingThread != null)
{
Stop();
e.Cancel = true;
}
}
} public class PageLink
{
string _name;
string _url;
bool _isFolder; public string Name { get { return _name; } }
public string Url { get { return _url; } }
public bool IsFolder { get { return _isFolder; } } public PageLink(string name, string url, bool isFolder)
{
_name = name;
_url = url;
_isFolder = isFolder;
}
}
/// <summary>
///
/// </summary>
public class FolderLinkData
{
string _url;
string _relativePath; public string Url { get { return _url; } }
public string RelativePath { get { return _relativePath; } } public FolderLinkData(string url, string relativePath)
{
_url = url;
_relativePath = relativePath;
}
}
/// <summary>
///
/// </summary>
public class FileDownloadData
{
string _url;
string _fileName; public string Url
{
get { return _url; }
} public string FileName
{
get { return _fileName; }
} public FileDownloadData(string url, string fileName)
{
_url = url;
_fileName = fileName;
}
}
}

  

csharp: Download SVN source的更多相关文章

  1. Download all Apple open source OS X files at once

    While it is well known that Mac OS X contains open source code, how to access and download that sour ...

  2. Spring 4 MVC example with Maven - [Source Code Download]

    In this tutorial, we show you a Spring 4 MVC example, using Maven build tool. Technologies used : Sp ...

  3. SVN服务之VisualSVN-Server和TortoiseSVN

    SVN客户端程序:TortoiseSVN SVN服务器程序:VisualSVN-Server   目前有个项目,需要版本服务器,由于习惯了svn的使用,让这边搭建一台svn服务器,做了一下整理,只满足 ...

  4. Windows下使用VisualSVN Server搭建SVN服务器

    使用 VisualSVN Server来实现主要的 SVN功能则要比使用原始的 SVN和 Apache相配合来实现源代码的 SVN管理简单的多,下面就看看详细的说明. VisualSVN Server ...

  5. How to build the Robotics Library from source code on Windows

    The Robotics Library is an open source C++ library for robot kinematics, motion planning and control ...

  6. PhoneGap奇怪的现象:File FileTransfer download, 手机相册检测不到下载下来的图片(解决)

    我有个从服务器下载相片的功能在使用 File FileTransfer download api时,碰到了很奇怪的现象:图片已经从服务器里下载了,手机文件夹里也可以看到下载过来的图片,但是我的手机相册 ...

  7. Installing Python 3.5.2 from source

    Here are the procedures we are to follow, Download the source code of an official Python release. Co ...

  8. pentaho kettle svn

    svn://source.pentaho.org/svnkettleroot/big data : svn://source.pentaho.org/svnkettleroot/archive/pen ...

  9. ionic cordova file download and load

    1.先添加插件 cordova plugin add org.apache.cordova.file cordova plugin add org.apache.cordova.file-transf ...

随机推荐

  1. PHP设计模式(八)桥接模式(Bridge For PHP)

    一.概述 桥接模式:将两个原本不相关的类结合在一起,然后利用两个类中的方法和属性,输出一份新的结果. 二.案例 1.模拟毛笔(转) 需求:现在需要准备三种粗细(大中小),并且有五种颜色的比 如果使用蜡 ...

  2. 软件工程(C编码实践篇)学习心得

    孟繁琛 + 原创作品转载请注明出处 + <软件工程(C编码实践篇)>MOOC课程 http://mooc.study.163.com/course/USTC-1000002006 软件工程 ...

  3. 烂泥:jira7.2安装、中文及破解

    . jira的主要配置文件,存放在/opt/atlassian/jira/conf/server.xml文件中,如下: vim /opt/atlassian/jira/conf/server.xml ...

  4. TFS 生成发布代理

    下载Agent 后,执行配置命令     参考 安装TFS(2015)工作组模式代理服务器(Agent)

  5. 基于AngularJs的上传控件-angular-file-upload

    今天跟大家分享的是一个依赖于angular的上传控件. 前段时间做项目遇到一个需求是上传文件,大概需要实现的样式是这样子的,见下图: 需要同时上传两个文件.并且规定文件格式和文件大小.因为前端框架使用 ...

  6. 【腾讯Bugly干货分享】Android动态布局入门及NinePatchChunk解密

    本文来自于腾讯bugly开发者社区,非经作者同意,请勿转载,原文地址:http://dev.qq.com/topic/57c7ff5d53bbcffd68c64411 作者:黄进——QQ音乐团队 摆脱 ...

  7. 基于java的分布式爬虫

    分类 分布式网络爬虫包含多个爬虫,每个爬虫需要完成的任务和单个的爬行器类似,它们从互联网上下载网页,并把网页保存在本地的磁盘,从中抽取URL并沿着这些URL的指向继续爬行.由于并行爬行器需要分割下载任 ...

  8. ABP(现代ASP.NET样板开发框架)系列之12、ABP领域层——工作单元(Unit Of work)

    点这里进入ABP系列文章总目录 基于DDD的现代ASP.NET开发框架--ABP系列之12.ABP领域层——工作单元(Unit Of work) ABP是“ASP.NET Boilerplate Pr ...

  9. ABP源码分析四:Configuration

    核心模块的配置 Configuration是ABP中设计比较巧妙的地方.其通过AbpStartupConfiguration,Castle的依赖注入,Dictionary对象和扩展方法很巧妙的实现了配 ...

  10. 阿里云自定义日记文件无法通过ftp下载

    异常处理汇总 ~ 修正果带着你的Net飞奔吧!http://www.cnblogs.com/dunitian/p/4599258.html 有可能是个例,xftp不行(对linux支持很好),Cute ...