クライアントからアップロード

	/// <summary>
	/// ファイルをアップロードする
	/// </summary>
	class FileUploader {
		string _uploadUrl;
		string _postInputName;
		Encoding _encode;
		CookieContainer _cookies;

		/// <summary>
		/// 文字コード、アップロードのアクションを指定してImageUploaderのインスタンスを初期化します。
		/// </summary>
		/// <param name="uploadUrl">アップロード用URL</param>
		/// <param name="encode">使用エンコード</param>
		/// <param name="cookies">利用するcookie</param>
		/// <param name="postInputName">アップロードアクション名</param>
		public FileUploader( string uploadUrl, Encoding encode, CookieContainer cookies = null, string postInputName = "upload" ) {
			_uploadUrl = uploadUrl;
			_encode = encode;
			_cookies = cookies;
			_postInputName = postInputName;
		}

		/// <summary>
		/// 文字コードをUTF-8としてImageUploaderのインスタンスを初期化します。
		/// </summary>
		/// <param name="uploadUrl">アップロード用URL</param>
		/// <param name="cookies">利用するcookie</param>
		public FileUploader( string uploadUrl, CookieContainer cookies = null ) {
			_uploadUrl = uploadUrl;
			_encode = Encoding.UTF8;
			_cookies = cookies;
		}

		/// <summary>
		/// 指定されたURLに対してMemoryStreamの内容をpoutする。
		/// </summary>
		/// <param name="memoryStream">アップロードデータ</param>
		/// <param name="fileName">アップロードファイル名</param>
		/// <returns>サーバーからの応答</returns>
		public string PostMemoryImage( MemoryStream memoryStream, string fileName ) {
			string boundary = GetBoundary();

			var request = (HttpWebRequest)WebRequest.Create( _uploadUrl );

			request.Method = "POST";
			request.ContentType = "multipart/form-data; boundary=" + boundary;
			request.CookieContainer = _cookies;

			var header = CreateHeader( fileName, boundary );
			var closeDelimiter = _encode.GetBytes( "\r\n--" + boundary + "--\r\n" );

			request.ContentLength = header.Length + memoryStream.Length + closeDelimiter.Length;

			SendData( request, header, memoryStream, closeDelimiter );

			var res = (HttpWebResponse)request.GetResponse();
			using ( var resStream = res.GetResponseStream() ) {
				using ( var reader = new StreamReader( resStream, _encode ) ) {
					return reader.ReadToEnd();
				}
			}
		}

		/// <summary>
		/// 区切り文字作成
		/// </summary>
		private static string GetBoundary() {
			var guidValue = Guid.NewGuid();
			string boundary = guidValue.ToString( "N" );
			return boundary;
		}

		/// <summary>
		/// アップロードするデータを送信する。
		/// </summary>
		/// <param name="request">送信リクエスト</param>
		/// <param name="header">multipartヘッダ</param>
		/// <param name="memoryStream">アップロードデータ</param>
		/// <param name="closeDelimiter">終端データ</param>
		private static void SendData( HttpWebRequest request, byte[] header, MemoryStream memoryStream, byte[] closeDelimiter ) {
			using ( var reqStream = request.GetRequestStream() ) {
				reqStream.Write( header, 0, header.Length );

				byte[] readData = new byte[0x1000];
				int maxCount = (int)( memoryStream.Length / readData.Length ) + 1;
				int readCount = 0;
				memoryStream.Position = 0;
				while ( readCount < maxCount ) {
					memoryStream.Read( readData, 0, readData.Length );
					reqStream.Write( readData, 0, GetNextReadSize( memoryStream, readData, readCount ) );
					readCount++;
				}

				reqStream.Write( closeDelimiter, 0, closeDelimiter.Length );
			}
		}

		private static int GetNextReadSize( MemoryStream memoryStream, byte[] readData, int readCount ) {
			return (int)Math.Min( readData.Length, memoryStream.Length - ( readCount * readData.Length ) );
		}

		/// <summary>
		/// multipart用ヘッダを作成する。
		/// </summary>
		/// <param name="fileName">アップロードファイル名</param>
		/// <param name="boundary">境界文字列</param>
		/// <returns>作成されたmultipart用ヘッダ</returns>
		private byte[] CreateHeader( string fileName, string boundary ) {
			var multipartHead = new StringBuilder();
			multipartHead.AppendFormat( "--{0}\r\n", boundary );
			multipartHead.AppendFormat( "{0}:{1}\r\n", "Content-Disposition"
				, string.Format( "form-data; name=\"{0}\"; filename=\"{1}\"", _postInputName, fileName )
			);
			multipartHead.AppendFormat( "{0}:{1}\r\n", "Content-Type", "application/octet-stream" );
			multipartHead.AppendFormat( "{0}:{1}\r\n", "Content-Transfer-Encoding", "binary" );
			multipartHead.Append( "\r\n" );

			return _encode.GetBytes( multipartHead.ToString() );
		}
	}

	/// <summary>
	/// 画像ファイルをアップロードする
	/// </summary>
	class ImageUploader : FileUploader {

		public ImageFormat ImageFormat { get; set; }

		/// <summary>
		/// 文字コード、アップロードのアクションを指定してImageUploaderのインスタンスを初期化します。
		/// </summary>
		/// <param name="uploadUrl">アップロード用URL</param>
		/// <param name="encode">使用エンコード</param>
		/// <param name="cookies">利用するcookie</param>
		/// <param name="postInputName">アップロードアクション名</param>
		public ImageUploader( string uploadUrl, Encoding encode, CookieContainer cookies = null, string postInputName = "upload" )
			: base( uploadUrl, encode, cookies, postInputName ) {
		}

		/// <summary>
		/// 文字コードをUTF-8としてImageUploaderのインスタンスを初期化します。
		/// </summary>
		/// <param name="uploadUrl">アップロード用URL</param>
		/// <param name="cookies">利用するcookie</param>
		public ImageUploader( string uploadUrl, CookieContainer cookies = null )
			: base( uploadUrl, cookies ) {
		}

		/// <summary>
		/// 画像のアップロードを行う。
		/// </summary>
		/// <param name="image">対象画像</param>
		public string UploadImage( Image image ) {
			using ( var memoryStream = new MemoryStream() ) {
				FillPngData( image, memoryStream );
				return PostMemoryImage( memoryStream, NameingImageFile() );
			}
		}

		private void FillPngData( Image image, MemoryStream memoryStream ) {
			image.Save( memoryStream, ImageFormat == null ? image.RawFormat : ImageFormat );
		}

		private string NameingImageFile() {
			return DateTime.Now.ToString( "yyyyMMddHHmmssfff" ) + GetExtention();
		}

		string GetExtention() {
			if ( ImageFormat == ImageFormat.Png ) {
				return ".png";
			}
			if ( ImageFormat == ImageFormat.Jpeg ) {
				return ".jpg";
			}
			return "";
		}
	}