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. MVC通过路由实现URL重写

    public static class WebApiConfig { public static void Register(HttpConfiguration config) { config.Ro ...

  2. Http请求

    HTTP报文是面向文本的,报文中的每一个字段都是一些ASCII码串,各个字段的长度是不确定的.HTTP有两类报文:请求报文和响应报文. 请求报文 一个HTTP请求报文由请求行(request line ...

  3. Unity3D框架插件uFrame实践记录(二)

    5.创建属性和命令 本小节主要内容包括: 在Element节点上创建属性数据 在Element节点上创建命令数据 5.1.在Element节点上创建属性数据 在这里,我们首先为Login节点中的属性( ...

  4. JavaScript 正则表达式语法

    定义 JavaScript定义正则表达式有两种方法. 1.RegExp构造函数 var pattern = new RegExp("[bc]at","i"); ...

  5. ios 获取或修改网页上的内容

    UIWebView是iOS最常用的SDK之一,它有一个stringByEvaluatingJavaScriptFromString方法可以将javascript嵌     入页面中,通过这个方法我们可 ...

  6. 驱动01.LED

    1.写出leds_open,leds_write函数2.1告诉内核这几个函数的存在?定义一个结构体file_operations2.2把这个结构体告诉内核?用register_chrdev(major ...

  7. SQL优化案例—— RowNumber分页

    将业务语句翻译成SQL语句不仅是一门技术,还是一门艺术. 下面拿我们程序开发工程师最常用的ROW_NUMBER()分页作为一个典型案例来说明. 先来看看我们最常见的分页的样子: WITH CTE AS ...

  8. Android Secret Code

    我们很多人应该都做过这样的操作,打开拨号键盘输入*#*#4636#*#*等字符就会弹出一个界面显示手机相关的一些信息,这个功能在Android中被称为android secret code,除了这些系 ...

  9. MySQL基础知识

    一.MySQL安装 MySQL的下载 http://dev.mysql.com/downloads/mysql/ MySQL版本选择 MySQL功能自定义选择安装 1.功能自定义选择 2.路径自定义选 ...

  10. Alcatraz 的安装和删除

    Xcode 所有的插件都安装在目录: ~/Library/Application Support/Developer/Shared/Xcode/Plug-ins/ 你也可以手工切换到这个目录来删除插件 ...