/// <summary> /// <paramref name="address"/>의 리소스를 비동기적으로 다운받아 byte array로 반환하는 Task{byte[]}를 빌드합니다. /// </summary> /// <param name="webClient"><see cref="WebClient"/> 인스턴스</param> /// <param name="token">작업 취소를 위한 Token</param> /// <param name="address">리소스 위치</param> /// <returns></returns> public static Task<byte[]> DownloadDataTask(this WebClient webClient, CancellationToken token, Uri address) { webClient.ShouldNotBeNull("webClient"); token.ShouldNotBeNull("token"); address.ShouldNotBeNull("address"); if(IsDebugEnabled) log.Debug("WebClient를 이용하여 지정된 주소로부터 리소스를 비동기 방식으로 다운받습니다... address=[{0}]", address.AbsoluteUri); var tcs = new TaskCompletionSource<byte[]>(address); token.Register(webClient.CancelAsync); // 비동기 완료 시의 처리를 정의합니다. DownloadDataCompletedEventHandler handler = null; handler = (sender, args) => EventAsyncPattern.HandleCompletion(tcs, args, () => args.Result, () => webClient.DownloadDataCompleted -= handler); webClient.DownloadDataCompleted += handler; try { webClient.DownloadDataAsync(address, tcs); } catch(Exception ex) { if(log.IsWarnEnabled) { log.Warn("WebClient를 이용하여 리소스 Data를 비동기적으로 다운받는데 실패했습니다. address=[{0}]", address.AbsoluteUri); log.Warn(ex); } webClient.DownloadDataCompleted -= handler; tcs.TrySetException(ex); } var result = tcs.Task; if(result.IsCompleted) result = result.ContinueWith(antecedent => DecompressByContentEncoding(webClient, antecedent.Result), TaskContinuationOptions.ExecuteSynchronously); return result; }
/// <summary> /// 지정된 Uri로부터, 리소스를 문자열로 비동기적으로 다운 받습니다. /// 인코딩 문제가 있을 때에는 <see cref="DownloadDataTask(System.Net.WebClient,System.Uri)"/>를 이용하여 Encoding을 직접 설정해 주시기 바랍니다. /// </summary> /// <param name="webClient"><see cref="WebClient"/> 인스턴스</param> /// <param name="token">작업 취소를 위한 Token</param> /// <param name="address">리소스 위치</param> /// <returns></returns> public static Task<string> DownloadStringTask(this WebClient webClient, CancellationToken token, Uri address) { webClient.ShouldNotBeNull("webClient"); token.ShouldNotBeNull("token"); address.ShouldNotBeNull("address"); if(IsDebugEnabled) log.Debug("WebClient로 지정된 주소로부터 비동기적으로 문자열을 다운받습니다... address=[{0}]", address.AbsoluteUri); // NOTE: 압축 통신시 응답 정보가 압축되어 있을 경우, 압축해제해서 결과를 반환해야 한다. 그래서 DownloadDataTask를 사용한다. // #if !SILVERLIGHT return DownloadDataTask(webClient, token, address) .ContinueWith(antecedent => antecedent.Result.ToText(), TaskContinuationOptions.ExecuteSynchronously); #else return DownloadStringTaskInternal(webClient, CancellationToken.None, address); #endif }
/// <summary> /// <paramref name="address"/>에 비동기적으로 data를 전송하기 위한 쓰기용 Stream을 반환합니다. /// </summary> /// <param name="webClient">WebClient 인스턴스</param> /// <param name="token">작업 취소를 위한 Token</param> /// <param name="address">리소스의 주소</param> /// <param name="method">전송 방법 : Http인 경우는 POST, FTP인 경우는 STOR입니다.</param> /// <returns></returns> public static Task<Stream> OpenWriteTask(this WebClient webClient, CancellationToken token, Uri address, string method) { webClient.ShouldNotBeNull("webClient"); token.ShouldNotBeNull("token"); address.ShouldNotBeNull("address"); if(IsDebugEnabled) log.Debug("지정된 주소에 데이타 쓰기용 Stream을 엽니다... address=[{0}], method=[{1}]", address.AbsoluteUri, method); var tcs = new TaskCompletionSource<Stream>(address); token.Register(webClient.CancelAsync); OpenWriteCompletedEventHandler handler = null; handler = (s, e) => EventAsyncPattern.HandleCompletion(tcs, e, () => e.Result, () => webClient.OpenWriteCompleted -= handler); webClient.OpenWriteCompleted += handler; try { webClient.OpenWriteAsync(address, method, tcs); } catch(Exception ex) { if(log.IsWarnEnabled) { log.Warn("WebClient를 이용하여 데이타를 전송하기 위해 쓰기용 Stream을 오픈하는데 실패했습니다. address=[{0}]", address.AbsoluteUri); log.Warn(ex); } webClient.OpenWriteCompleted -= handler; tcs.TrySetException(ex); } return tcs.Task; }
/// <summary> /// <paramref name="address"/>의 리소스 정보를 비동기적으로 다운받아 파일로 저장합니다. /// </summary> /// <param name="webClient"></param> /// <param name="token">작업 취소용 Token</param> /// <param name="address">다운 받을 리소스의 주소</param> /// <param name="filename">다운로드 리소스를 저장할 로컬 파일명</param> /// <returns></returns> public static Task DownloadFileTask(this WebClient webClient, CancellationToken token, Uri address, string filename) { webClient.ShouldNotBeNull("webClient"); token.ShouldNotBeNull("token"); address.ShouldNotBeNull("address"); filename.ShouldNotBeWhiteSpace("filename"); if(IsDebugEnabled) log.Debug("WebClient를 이용하여 지정된 주소의 리소스를 비동기적으로 다운받아 파일로 저장합니다... address=[{0}], filename=[{1}]", address.AbsoluteUri, filename); // NOTE: 압축 통신을 대비해서, Byte 통신 후, 저장한다. // return DownloadDataTask(webClient, token, address) .ContinueWith(antecedent => FileAsync.WriteAllBytes(filename, antecedent.Result), TaskContinuationOptions.ExecuteSynchronously); }