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. git-2.10.2-64-bit介绍&&git下载&&git安装教程

    Git介绍 分布式:Git系统是一个分布式的系统,是用来保存工程源代码历史状态的命令行工具. 保存点:Git的保存点可以追踪源码中的文件, 并能得到某一个时间点上的整个工程项目的状态:可以在该保存点将 ...

  2. iOS架构一个中型普通App的一些经验总结

    这一版比较完善的的App终于提交审核了.有时间写写自己的一些经验的总结了.自己主导的从0到比较成型的app到目前来说也只有两个,但是其中的很多东西都是大同小异.基本上是想到了什么就写什么,感觉写的不到 ...

  3. Cesium简介以及离线部署运行

    Cesium简介 cesium是国外一个基于JavaScript编写的使用WebGL的地图引擎,一款开源3DGIS的js库.cesium支持3D,2D,2.5D形式的地图展示,可以自行绘制图形,高亮区 ...

  4. SharePoint 2016 入门视频教程

    之前一直有朋友让自己录一些SharePoint的入门视频,之前没有太多时间,一个巧合的机会收到CSDN学院的邮件,可以在CSDN上发布视频教程,自己就录了一些.说起录视频也是蛮辛苦的,每天下班吃完饭要 ...

  5. MongoDB备份(mongodump)和恢复(mongorestore)

    MongoDB提供了备份和恢复的功能,分别是MongoDB下载目录下的mongodump.exe和mongorestore.exe文件 1.备份数据使用下面的命令: >mongodump -h ...

  6. SpringMVC(关于HandlerMapping执行流程原理分析)

    请求过来先碰见中央调度器(前端调度器) //Determine handler for the current request; 对当前请求决定交给哪个handler, 当前请求地址过来 处理器执行链 ...

  7. 山寨Unity3D?搜狐畅游的免费开源游戏引擎Genesis-3D

    在CSDN上看到了<搜狐畅游发布3D游戏引擎Genesis-3D 基于MIT协议开源>(http://www.csdn.net/article/2013-11-21/2817585-cha ...

  8. 分布式服务注册和发现consul 简要介绍

    Consul是HashiCorp公司推出的开源工具,用于实现分布式系统的服务发现与配置.与其他分布式服务注册与发现的方案,Consul的方案更"一站式",内置了服务注册与发现框 架 ...

  9. AutoMapper(二)

    返回总目录 首先,先创建一个控制台项目,引用AutoMapper程序集,创建三个类User,UserDto,UserMappingProfile,下面的知识点的演示都以此项目为基础,代码分别如下: n ...

  10. 如何在VMware中安装Windows Phone SDK 8.0 (支持模拟器调试)

    相信很多开发者目前的系统还是Win7或Mac,一般不会为了开发某个程序而重装系统,所以我们就需要用到VMware这类的虚拟机来模拟预期的开发环境.在开始介绍前,给大家说明下我当前的软硬件环境,本文所讲 ...