Skip to content

Instantly share code, notes, and snippets.

@kiyokura
Created May 11, 2012 01:21
Show Gist options
  • Save kiyokura/2656920 to your computer and use it in GitHub Desktop.
Save kiyokura/2656920 to your computer and use it in GitHub Desktop.
フォルダ作成とファイルアップロードする為だけの簡易WebDAVクライアントClass
using System;
using System.Net;
using System.IO;
using System.Diagnostics;
namespace TinyWebDav
{
/// <summary>
/// 簡易WebDAVクライアントクラス
/// </summary>
public class WebDavClient
{
#region "プライベートフィールド"
private string userName;
private string userPassword;
private string baseUrl;
#endregion
#region"コンストラクタ"
/// <summary>
/// コンストラクタ
/// </summary>
/// <param name="userName">ユーザ名</param>
/// <param name="userPassword">パスワード</param>
/// <param name="baseUrl">ベースURL</param>
public WebDavClient(string userName, string userPassword, string baseUrl)
{
if (string.IsNullOrEmpty(userName))
{
throw new AggregateException("ユーザ名が空です");
}
if (string.IsNullOrEmpty(baseUrl))
{
throw new AggregateException("ベースが空です");
}
this.userName = userName;
this.userPassword = userPassword;
this.baseUrl = baseUrl;
}
#endregion
#region"ファイルアップロード"
/// <summary>
/// ファイルアップロード
/// </summary>
/// <param name="folderName">アップロード対象フォルダ</param>
/// <param name="localPath">アップロード対象ファイルのローカルパス(フルパス)</param>
/// <returns>HTTPレスポンスコード</returns>
/// <remarks>アップロード後のファイル名はローカルにあるものと同じになる。同一ファイル名は上書きされる。</remarks>
public HttpStatusCode UploadFile(string folderName, string localPath)
{
return UploadFile(folderName, localPath, Path.GetFileName(localPath));
}
/// <summary>
/// ファイルアップロード
/// </summary>
/// <param name="folderName">アップロード先のフォルダ名(ルートに置く場合は空で)</param>
/// <param name="localPath">アップロード対象ファイルのローカルパス(フルパス)</param>
/// <param name="uploadedFileName">アップロード後のファイル名</param>
/// <returns>HTTPレスポンスコード</returns>
/// <remarks>同一ファイル名は上書きされる。</remarks>
public HttpStatusCode UploadFile(string folderName, string localPath, string uploadedFileName)
{
#region"引数チェック"
if (!File.Exists(localPath))
throw new FileNotFoundException(string.Format("指定されたファイル<{0}>が存在しません", localPath));
if (string.IsNullOrEmpty(uploadedFileName))
throw new ArgumentException("アップロード後ファイル名が未指定です");
if (uploadedFileName.IndexOfAny(Path.GetInvalidFileNameChars()) > 0)
throw new ArgumentException(string.Format("指定されたファイル名<{0}>に使用不可能な文字が含まれています", uploadedFileName));
#endregion
try
{
// HttpWebRequestを初期化
var req = httpWebRequestFactory(makeUrl(folderName, uploadedFileName));
req.Method = WebRequestMethods.File.UploadFile;
// アップロードするファイルをオープン
using (FileStream inSt = new FileStream(localPath, FileMode.Open))
{
//HttpWebRequestにサイズを設定
req.ContentLength = inSt.Length;
// ファイルをバッファに読み込み・サーバーへ書き込み
using (Stream outSt = req.GetRequestStream())
{
int bufSize = 1024*1024;
byte[] buffer = new byte[bufSize];
int bytesReaded = 0;
while ((bytesReaded = inSt.Read(buffer, 0, bufSize)) > 0)
{
outSt.Write(buffer, 0, bytesReaded);
}
outSt.Flush();
}
}
// 結果取得
using (HttpWebResponse res = (HttpWebResponse)req.GetResponse())
{
return res.StatusCode;
}
}
catch (WebException we)
{
var errResponse = (HttpWebResponse)we.Response;
Debug.WriteLine(errResponse.Headers.ToString());
Debug.WriteLine("Status Code: {0}", errResponse.StatusCode);
throw;
}
}
#endregion
#region"フォルダ作成"
/// <summary>
/// フォルダ作成
/// </summary>
/// <param name="path">作成したいパス(ルート以下を全て記述)</param>
/// <returns>
/// </returns>
/// <remarks>
/// 上位のパスが存在しない場合、例外(409)が発生する。
/// </remarks>
public HttpStatusCode CreateFolder(string path)
{
#region"引数チェック"
if (string.IsNullOrEmpty(path))
throw new ArgumentException("引数pathはNullにはできません");
#endregion
try
{
var req = httpWebRequestFactory(makeUrl(path));
req.Method = WebRequestMethods.Http.MkCol;
using (HttpWebResponse res = (HttpWebResponse)req.GetResponse())
{
return res.StatusCode;
}
}
catch (WebException we)
{
var errResponse = (HttpWebResponse)we.Response;
Debug.WriteLine(errResponse.Headers.ToString());
Debug.WriteLine("Status Code: {0}", errResponse.StatusCode);
throw;
}
}
#endregion
#region "存在チェック"
/// <summary>
/// パスが存在するかチェック
/// </summary>
/// <param name="folerName"></param>
/// <param name="fileName"></param>
/// <returns></returns>
public bool Exists(string folerName, string fileName)
{
var req = httpWebRequestFactory(makeUrl(folerName,fileName));
req.Method = WebRequestMethods.Http.Head;
HttpWebResponse res;
try
{
using (res = (HttpWebResponse)req.GetResponse())
{
switch (res.StatusCode)
{
case HttpStatusCode.OK:
// このあたりは多分OK。
return true;
default:
Debug.WriteLine(res.Headers.ToString());
Debug.WriteLine("Status Code: {0}", res.StatusCode);
return false;
}
}
}
catch (WebException we)
{
var errResponse = (HttpWebResponse)we.Response;
switch (errResponse.StatusCode)
{
case HttpStatusCode.Forbidden:
// 403だけど帰ってきてるので、存在はしている(と思われる)
return true;
case HttpStatusCode.NotFound:
// 404なので、これは無い。
return false;
default:
// 他はとりあえずthrowする。
Debug.WriteLine(errResponse.Headers.ToString());
Debug.WriteLine("Status Code: {0}", errResponse.StatusCode);
throw;
}
}
}
/// <summary>
/// パス(ルート以下)が存在するかチェック
/// </summary>
/// <param name="path">ルート以下のパス</param>
/// <returns></returns>
public bool Exists(string path)
{
var req = httpWebRequestFactory(makeUrl(path));
req.Method = WebRequestMethods.Http.Head;
HttpWebResponse res;
try
{
using (res = (HttpWebResponse)req.GetResponse())
{
switch (res.StatusCode)
{
case HttpStatusCode.OK:
// このあたりは多分OK。
return true;
default:
Debug.WriteLine(res.Headers.ToString());
Debug.WriteLine("Status Code: {0}", res.StatusCode);
return false;
}
}
}
catch (WebException we)
{
var errResponse = (HttpWebResponse)we.Response;
switch (errResponse.StatusCode)
{
case HttpStatusCode.Forbidden:
// 403だけど帰ってきてるので、存在はしている(と思われる)
return true;
case HttpStatusCode.NotFound:
// 404なので、これは無い。
return false;
default:
// 他はとりあえずthrowする。
Debug.WriteLine(errResponse.Headers.ToString());
Debug.WriteLine("Status Code: {0}", errResponse.StatusCode);
throw;
}
}
}
#endregion
#region"ヘルパ"
/// <summary>
/// HttpWebRequestファクトリー
/// </summary>
/// <param name="url"></param>
/// <returns></returns>
private HttpWebRequest httpWebRequestFactory(string url)
{
HttpWebRequest req = (HttpWebRequest)HttpWebRequest.Create(url);
req.Credentials = new NetworkCredential(userName, userPassword);
return req;
}
/// <summary>
/// リクエスト用のURL作成
/// </summary>
/// <param name="folderName"></param>
/// <param name="fileName"></param>
/// <returns></returns>
private string makeUrl(string folderName , string fileName)
{
return this.baseUrl.TrimEnd("/".ToCharArray()) + "/" + folderNameNormalizer(folderName) + fileNameNormalizer(fileName);
}
/// <summary>
/// リクエスト用のURL作成
/// </summary>
/// <param name="folderName"></param>
/// <returns></returns>
private string makeUrl(string path)
{
return this.baseUrl.TrimEnd("/".ToCharArray()) + "/" + pathNormalizer(path);
}
/// <summary>
/// フォルダ名URL正規化
/// </summary>
/// <param name="folderName"></param>
/// <returns>
/// 正規化された、URL用のフォルダ名(先頭のスラッシュ無し、末尾にスラッシュあり)
/// ただし、空文字列の場合はスラッシュ無。
/// </returns>
private string folderNameNormalizer(string folderName)
{
if (string.IsNullOrEmpty(folderName))
{
return "";
}
else
{
return folderName.TrimEnd("/".ToCharArray()).TrimStart("/".ToCharArray()) + "/";
}
}
/// <summary>
/// ファイル名URL正規化
/// </summary>
/// <param name="fileName"></param>
/// <returns>
/// 正規化された、URL用のファイル名(先頭のスラッシュ無し)
/// </returns>
private string fileNameNormalizer(string fileName)
{
return fileName.TrimStart("/".ToCharArray());
}
/// <summary>
/// パス(ルート以下)の正規化
/// </summary>
/// <param name="path">パス(ルート以下)</param>
/// <returns>
/// 正規化された、URL用のパス名(先頭のスラッシュ無し)
/// 末尾にもスラッシュは付与しない(ファイル名のケースを考慮)
/// </returns>
private string pathNormalizer(string path)
{
return path.TrimStart("/".ToCharArray());
}
#endregion
}
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment