Sak*_*ket 19 .net c# rest webclient httpclient
我试图从URL下载文件,我必须在WebClient和HttpClient之间进行选择.我在互联网上引用了这篇文章和其他几篇文章.无处不在,由于其非常好的异步支持和其他.Net 4.5权限,建议使用HttpClient.但我仍然不完全相信并需要更多的投入.
我使用下面的代码从互联网上下载文件:
Web客户端:
WebClient client = new WebClient();
client.DownloadFile(downloadUrl, filePath);
Run Code Online (Sandbox Code Playgroud)
HttpClient的:
using (HttpClient client = new HttpClient())
{
using (HttpResponseMessage response = await client.GetAsync(url))
using (Stream streamToReadFrom = await response.Content.ReadAsStreamAsync())
{
}
}
Run Code Online (Sandbox Code Playgroud)
从我的角度来看,我只能看到使用WebClient的一个缺点,那就是非异步调用,阻塞调用线程.但是,如果我不担心阻塞线程或使用client.DownloadFileAsync()异步支持,该怎么办?
另一方面,如果我使用HttpClient,是不是我将文件的每个字节加载到内存中然后将其写入本地文件?如果文件太大,内存开销不会很贵吗?如果我们使用WebClient可以避免这种情况,因为它将直接写入本地文件而不会消耗系统内存.
那么,如果性能是我的首要任务,我应该使用哪种方法进行下载?如果我的上述假设是错误的,我想澄清一下,我也愿意接受替代方法.
Blu*_*ron 31
您可以使用 .Net 4.5+ 本地完成。我试着按照你的方式去做,然后我在 Intellisense 中找到了一种似乎有意义的方法。
https://docs.microsoft.com/en-us/dotnet/api/system.io.stream.copytoasync?view=netframework-4.7.2
uri = new Uri(generatePdfsRetrieveUrl + pdfGuid + ".pdf");
HttpClient client = new HttpClient();
var response = await client.GetAsync(uri);
using (var fs = new FileStream(
HostingEnvironment.MapPath(string.Format("~/Downloads/{0}.pdf", pdfGuid)),
FileMode.CreateNew))
{
await response.Content.CopyToAsync(fs);
}
Run Code Online (Sandbox Code Playgroud)
Ton*_*ony 29
为了在使用 WebClient 的现有代码上使用 HttpClient,我编写了一个小的扩展方法,以与DownloadFileTaskAsync在代码中使用的相同方式使用它。
using (var client = new System.Net.Http.HttpClient()) // WebClient
{
var fileName = @"C:\temp\imgd.jpg";
var uri = new Uri("https://yourwebsite.com/assets/banners/Default.jpg");
await client.DownloadFileTaskAsync(uri, fileName);
}
Run Code Online (Sandbox Code Playgroud)
要使用它,我们可以使用以下扩展方法:
public static class HttpClientUtils
{
public static async Task DownloadFileTaskAsync(this HttpClient client, Uri uri, string FileName)
{
using (var s = await client.GetStreamAsync(uri))
{
using (var fs = new FileStream(FileName, FileMode.CreateNew))
{
await s.CopyToAsync(fs);
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的方法。
如果要调用WebApi来获取文件,则可以从控制器方法中使用HttpClient GET请求,并使用FileStreamResult返回类型返回文件流。
public async Task<ActionResult> GetAttachment(int FileID)
{
UriBuilder uriBuilder = new UriBuilder();
uriBuilder.Scheme = "https";
uriBuilder.Host = "api.example.com";
var Path = "/files/download";
uriBuilder.Path = Path;
using (HttpClient client = new HttpClient())
{
client.BaseAddress = new Uri(uriBuilder.ToString());
client.DefaultRequestHeaders.Accept.Clear();
client.DefaultRequestHeaders.Add("authorization", access_token); //if any
client.DefaultRequestHeaders.Accept.Add(new System.Net.Http.Headers.MediaTypeWithQualityHeaderValue("application/json"));
HttpResponseMessage response = await client.GetAsync(uriBuilder.ToString());
if (response.IsSuccessStatusCode)
{
System.Net.Http.HttpContent content = response.Content;
var contentStream = await content.ReadAsStreamAsync(); // get the actual content stream
return File(contentStream, content_type, filename);
}
else
{
throw new FileNotFoundException();
}
}
}
Run Code Online (Sandbox Code Playgroud)
对于重复调用的代码,您不想放入块HttpClient中using(它会使挂起的端口保持打开状态)
为了使用 HttpClient 下载文件,我发现了这个扩展方法,这对我来说似乎是一个很好且可靠的解决方案:
public static class HttpContentExtensions
{
public static Task ReadAsFileAsync(this HttpContent content, string filename, bool overwrite)
{
string pathname = Path.GetFullPath(filename);
if (!overwrite && File.Exists(filename))
{
throw new InvalidOperationException(string.Format("File {0} already exists.", pathname));
}
FileStream fileStream = null;
try
{
fileStream = new FileStream(pathname, FileMode.Create, FileAccess.Write, FileShare.None);
return content.CopyToAsync(fileStream).ContinueWith(
(copyTask) =>
{
fileStream.Close();
});
}
catch
{
if (fileStream != null)
{
fileStream.Close();
}
throw;
}
}
}
Run Code Online (Sandbox Code Playgroud)
小智 5
这里\xe2\x80\x99s是使用它下载URL并将其保存到文件的一种方法:(我使用的是Windows 7,因此我没有可用的WindowsRT,所以我\xe2\x80\x99m也使用System.IO .)
\n\npublic static class WebUtils\n{\n private static Lazy<IWebProxy> proxy = new Lazy<IWebProxy>(() => string.IsNullOrEmpty(Settings.Default.WebProxyAddress) ? null : new WebProxy { Address = new Uri(Settings.Default.WebProxyAddress), UseDefaultCredentials = true });\n\n public static IWebProxy Proxy\n {\n get { return WebUtils.proxy.Value; }\n }\n\n public static Task DownloadAsync(string requestUri, string filename)\n {\n if (requestUri == null)\n throw new ArgumentNullException(\xe2\x80\x9crequestUri\xe2\x80\x9d);\n\n return DownloadAsync(new Uri(requestUri), filename);\n }\n\n public static async Task DownloadAsync(Uri requestUri, string filename)\n {\n if (filename == null)\n throw new ArgumentNullException("filename");\n\n if (Proxy != null)\n WebRequest.DefaultWebProxy = Proxy;\n\n using (var httpClient = new HttpClient())\n {\n using (var request = new HttpRequestMessage(HttpMethod.Get, requestUri))\n {\n using (Stream contentStream = await (await httpClient.SendAsync(request)).Content.ReadAsStreamAsync(), stream = new FileStream(filename, FileMode.Create, FileAccess.Write, FileShare.None, Constants.LargeBufferSize, true))\n {\n await contentStream.CopyToAsync(stream);\n }\n }\n }\n }\n} \nRun Code Online (Sandbox Code Playgroud)\n\n请注意,代码将我(在工作中)使用的代理服务器的地址保存在设置中,并在指定了此类设置的情况下使用该地址。否则,它应该告诉您有关使用 HttpClient beta 下载和保存文件所需了解的所有信息。
\n| 归档时间: |
|
| 查看次数: |
36396 次 |
| 最近记录: |