www.pudn.com > dotnetupdater.rar > WebFileLoader.cs
using System;
using System.IO;
using System.Net;
using System.Diagnostics;
using System.Windows.Forms;
using System.Text;
using System.Xml;
using System.Collections;
using System.Globalization;
namespace Microsoft.Samples.AppUpdater
{
//**************************************************************
// WebFileLoader class
// - Full of static helper methods for network & disk I/O
//**************************************************************
public class WebFileLoader
{
//**************************************************************
// CheckForFileUpdate()
// - Checks to see if a newer file is on the server
//**************************************************************
public static bool CheckForFileUpdate(string url, string filePath)
{
HttpWebRequest Request = (HttpWebRequest)HttpWebRequest.Create(url);
Request.Method = "HEAD";
Request.Credentials = CredentialCache.DefaultCredentials;
//Set up the last modfied time header
if (File.Exists(filePath))
Request.IfModifiedSince = LastModFromDisk(filePath);
HttpWebResponse Response;
try
{
Response = (HttpWebResponse)Request.GetResponse();
}
catch(WebException e)
{
if (e.Response == null)
{
Debug.WriteLine("Error accessing Url " + url);
throw;
}
HttpWebResponse errorResponse = (HttpWebResponse)e.Response;
//if the file has not been modified
if (errorResponse.StatusCode == HttpStatusCode.NotModified)
{
e.Response.Close();
return false;
}
else
{
e.Response.Close();
Debug.WriteLine("Error accessing Url " + url);
throw;
}
}
//This case happens if no lastmodedate was specified, but the specified
//file does exist on the server.
Response.Close();
return true;
}
//**************************************************************
// UpdateFile()
// - Copies the newer file on the server to the client
//**************************************************************
public static void UpdateFile(string url, string filePath)
{
HttpWebResponse Response;
//Retrieve the File
HttpWebRequest Request = (HttpWebRequest)HttpWebRequest.Create(url);
Request.Headers.Add("Translate: f");
Request.Credentials = CredentialCache.DefaultCredentials;
//Set up the last modfied time header
if (File.Exists(filePath))
Request.IfModifiedSince = LastModFromDisk(filePath);
try
{
Response = (HttpWebResponse)Request.GetResponse();
}
catch(WebException e)
{
if (e.Response == null)
{
Debug.WriteLine("Error accessing Url " + url);
throw;
}
HttpWebResponse errorResponse = (HttpWebResponse)e.Response;
//if the file has not been modified
if (errorResponse.StatusCode == HttpStatusCode.NotModified)
{
e.Response.Close();
return;
}
else
{
e.Response.Close();
Debug.WriteLine("Error accessing Url " + url);
throw;
}
}
Stream respStream = null;
try
{
respStream = Response.GetResponseStream();
CopyStreamToDisk(respStream,filePath);
DateTime d = System.Convert.ToDateTime(Response.GetResponseHeader("Last-Modified"));
File.SetLastWriteTime(filePath,d);
}
catch (Exception)
{
Debug.WriteLine("APPMANAGER: Error writing to: " + filePath);
throw;
}
finally
{
if (respStream != null)
respStream.Close();
if (Response != null)
Response.Close();
}
}
//**************************************************************
// CopyDirectory()
// Does a deep copy
// Returns the number of files copied
// If keys is null, validates assemblies copied have been signed
// by one of the provided keys.
//**************************************************************
public static int CopyDirectory(string url, string filePath)
{
Resource currentResource;
int FileCount = 0;
string newFilePath;
SortedList DirectoryList = WebFileLoader.GetDirectoryContents(url, false);
foreach(Object r in DirectoryList)
{
currentResource = (Resource)(((DictionaryEntry)r).Value);
//If the directory doesn't exist, create it first
if (!Directory.Exists(filePath))
Directory.CreateDirectory(filePath);
//If it's a file than copy the file.
if (!currentResource.IsFolder)
{
FileCount++;
newFilePath = filePath + currentResource.Name;
//only update the file if it doesn't exist or if the one on the server
//returned a newer last modtime than the one on disk
if (!File.Exists(newFilePath))
UpdateFile(currentResource.Url,newFilePath);
else
if (currentResource.LastModified > LastModFromDisk(newFilePath))
UpdateFile(currentResource.Url,newFilePath);
}
//If it's a folder, download the folder itself.
else
{
newFilePath = filePath + currentResource.Name + "\\";
FileCount += CopyDirectory(currentResource.Url,newFilePath);
}
}
return FileCount;
}
//**************************************************************
// GetDirectoryContents()
// - Uses HTTP/DAV to get a list of directories
//**************************************************************
public static SortedList GetDirectoryContents(string url, bool deep)
{
//Retrieve the File
HttpWebRequest Request = (HttpWebRequest)HttpWebRequest.Create(url);
Request.Headers.Add("Translate: f");
Request.Credentials = CredentialCache.DefaultCredentials;
string requestString = ""+
""+
""+
" "+
" "+
" "+
" "+
" ";
Request.Method = "PROPFIND";
if (deep == true)
Request.Headers.Add("Depth: infinity");
else
Request.Headers.Add("Depth: 1");
Request.ContentLength = requestString.Length;
Request.ContentType = "text/xml";
Stream requestStream = Request.GetRequestStream();
requestStream.Write(Encoding.ASCII.GetBytes(requestString),0,Encoding.ASCII.GetBytes(requestString).Length);
requestStream.Close();
HttpWebResponse Response;
StreamReader respStream;
try
{
Response = (HttpWebResponse)Request.GetResponse();
respStream = new StreamReader(Response.GetResponseStream());
}
catch (WebException e)
{
Debug.WriteLine("APPMANAGER: Error accessing Url " + url);
throw e;
}
StringBuilder SB = new StringBuilder();
char[] respChar = new char[1024];
int BytesRead = 0;
BytesRead = respStream.Read(respChar,0,1024);
while (BytesRead>0)
{
SB.Append(respChar,0,BytesRead);
BytesRead = respStream.Read(respChar,0,1024);
}
respStream.Close();
XmlDocument XmlDoc = new XmlDocument();
XmlDoc.LoadXml(SB.ToString());
//Create an XmlNamespaceManager for resolving namespaces.
XmlNamespaceManager nsmgr = new XmlNamespaceManager(XmlDoc.NameTable);
nsmgr.AddNamespace("a", "DAV:");
XmlNodeList NameList = XmlDoc.SelectNodes("//a:prop/a:displayname",nsmgr);
XmlNodeList isFolderList = XmlDoc.SelectNodes("//a:prop/a:iscollection",nsmgr);
XmlNodeList LastModList = XmlDoc.SelectNodes("//a:prop/a:getlastmodified",nsmgr);
XmlNodeList HrefList = XmlDoc.SelectNodes("//a:href",nsmgr);
SortedList ResourceList = new SortedList();
Resource tempResource;
for (int i=0; i < NameList.Count; i++)
{
//This check is needed because the PROPFIND request returns the contents of the folder
//as well as the folder itself. Exclude the folder.
if (HrefList[i].InnerText.ToLower(new CultureInfo("en-US")).TrimEnd(new char[] {'/'}) != url.ToLower(new CultureInfo("en-US")).TrimEnd(new char[] {'/'}))
{
tempResource = new Resource();
tempResource.Name = NameList[i].InnerText;
tempResource.IsFolder = Convert.ToBoolean(Convert.ToInt32(isFolderList[i].InnerText));
tempResource.Url = HrefList[i].InnerText;
tempResource.LastModified = Convert.ToDateTime(LastModList[i].InnerText);
ResourceList.Add(tempResource.Url,tempResource);
}
}
return ResourceList;
}
//**************************************************************
// UpdateFileList()
// - A multi-file UpdateFile
//**************************************************************
public static void UpdateFileList(SortedList fileList, string sourceUrl, string destPath)
{
Resource currentResource;
//If the directory doesn't exist, create it first
if (!Directory.Exists(destPath))
Directory.CreateDirectory(destPath);
foreach(Object o in fileList)
{
currentResource = (Resource)(((DictionaryEntry)o).Value);
string url = sourceUrl + currentResource.Name;
string FilePath = destPath + currentResource.Name;
WebFileLoader.UpdateFile(url,FilePath);
}
}
//**************************************************************
// GetLastModTime()
// - Gets the last mode time for a file on the server
//**************************************************************
public static DateTime GetLastModTime(string url)
{
HttpWebResponse Response;
HttpWebRequest Request = (HttpWebRequest)HttpWebRequest.Create(url);
Request.Method = "HEAD";
try
{
Response = (HttpWebResponse)Request.GetResponse();
}
catch(WebException e)
{
Debug.WriteLine("Error accessing Url " + url);
if (e.Response != null)
e.Response.Close();
throw;
}
DateTime d = System.Convert.ToDateTime(Response.GetResponseHeader("Last-Modified"));
return d;
}
//**************************************************************
// LoadFile()
// - Returns a stream to a file on a web server
//**************************************************************
public static Stream LoadFile(string url)
{
HttpWebResponse Response;
//Retrieve the File
HttpWebRequest Request = (HttpWebRequest)HttpWebRequest.Create(url);
try
{
Response = (HttpWebResponse)Request.GetResponse();
}
catch(WebException)
{
Debug.WriteLine("Error accessing Url " + url);
throw;
}
return Response.GetResponseStream();
}
//**************************************************************
// CheckForFileUpdate()
// - Checks if the file on the server is newer than the given date
//**************************************************************
public static bool CheckForFileUpdate(string url, DateTime lastModeTime)
{
HttpWebRequest Request = (HttpWebRequest)HttpWebRequest.Create(url);
Request.Method = "HEAD";
Request.IfModifiedSince = lastModeTime;
HttpWebResponse Response;
try
{
Response = (HttpWebResponse)Request.GetResponse();
}
catch(WebException e)
{
if (e.Response == null)
{
Debug.WriteLine("Error accessing Url " + url);
throw;
}
HttpWebResponse errorResponse = (HttpWebResponse)e.Response;
//if the file has not been modified
if (errorResponse.StatusCode == HttpStatusCode.NotModified)
{
e.Response.Close();
return false;
}
else
{
e.Response.Close();
Debug.WriteLine("Error accessing Url " + url);
throw;
}
}
//This case happens if no lastmodedate was specified, but the specified
//file does exist on the server.
Response.Close();
return true;
}
//**************************************************************
// GetFileCount()
// - Gets the list of files on the server. Useful when downloading
// many files and you need the file count for a progress indicator
//**************************************************************
public static int GetFileCount(string filePath)
{
string[] directories = Directory.GetDirectories(filePath);
string[] files = Directory.GetFiles(filePath);
string name;
int count=0;
count = files.Length + directories.Length;
foreach (string directory in directories)
{
name = directory.Remove(0,directory.LastIndexOf("\\")+1);
count = count + GetFileCount(filePath + name + "\\");
}
return count;
}
//**************************************************************
// CopyStreamToDisk()
//**************************************************************
private static void CopyStreamToDisk(Stream responseStream, String filePath)
{
byte[] buffer = new byte[4096];
int length;
//Copy to a temp file first so that if anything goes wrong with the network
//while downloading the file, we don't actually update the real on file disk
//This essentially gives us transaction like semantics.
Random Rand = new Random();
string tempPath = Environment.GetEnvironmentVariable("temp") + "\\";
tempPath += filePath.Remove(0,filePath.LastIndexOf("\\")+1);
tempPath += Rand.Next(10000).ToString() + ".tmp";
FileStream AFile = File.Open(tempPath,FileMode.Create,FileAccess.ReadWrite);
length = responseStream.Read(buffer,0,4096);
while ( length > 0)
{
AFile.Write(buffer,0,length);
length = responseStream.Read(buffer,0,4096);
}
AFile.Close();
if (File.Exists(filePath))
File.Delete(filePath);
File.Move(tempPath,filePath);
}
//**************************************************************
// LastModFromDisk()
//**************************************************************
public static DateTime LastModFromDisk(string filePath)
{
FileInfo f = new FileInfo(filePath);
return (f.LastWriteTime);
}
//**************************************************************
// CopyAndRename()
//**************************************************************
public static void CopyAndRename(string source, string dest)
{
string[] directories = Directory.GetDirectories(source);
string[] files = Directory.GetFiles(source);
string name;
//If the directory doesn't exist, create it first
if (!Directory.Exists(dest))
Directory.CreateDirectory(dest);
foreach (string file in files)
{
name = file.Remove(0,file.LastIndexOf("\\")+1);
MessageBox.Show(name);
if (File.Exists(dest+name))
File.Delete(dest+name);
File.Move(file, dest+name);
}
foreach (string directory in directories)
{
name = directory.Remove(0,directory.LastIndexOf("\\")+1);
MessageBox.Show(name);
if (!Directory.Exists(dest + name + "\\"))
Directory.CreateDirectory(dest + name + "\\");
CopyAndRename(source + name + "\\", dest + name + "\\");
}
Directory.Delete(source,true);
}
//**************************************************************
// CreateHttpsUrl()
//**************************************************************
public static string CreateHttpsUrl(string url)
{
url = url.ToLower(new CultureInfo("en-US"));
if (url.StartsWith("https"))
return url;
else
{
return url.Insert(4,"s");
}
}
}
}