如何使用 httpwebrequest 将图像从网站拉到本地文件
Posted
技术标签:
【中文标题】如何使用 httpwebrequest 将图像从网站拉到本地文件【英文标题】:How to use httpwebrequest to pull image from website to local file 【发布时间】:2011-01-23 00:16:34 【问题描述】:我正在尝试使用本地 c# 应用程序将一些图像从网站拉到本地计算机上的文件中。我正在使用下面列出的代码。我尝试了 ASCII 编码和 UTF8 编码,但最终文件不正确。有谁看到我做错了什么?当我将地址放入浏览器时,该网址是有效且正确的,并且可以很好地显示图像。
private void button1_Click(object sender, EventArgs e)
HttpWebRequest lxRequest = (HttpWebRequest)WebRequest.Create("http://www.productimageswebsite.com/images/stock_jpgs/34891.jpg");
// returned values are returned as a stream, then read into a string
String lsResponse = string.Empty;
HttpWebResponse lxResponse = (HttpWebResponse)lxRequest.GetResponse();
using (StreamReader lxResponseStream = new StreamReader(lxResponse.GetResponseStream()))
lsResponse = lxResponseStream.ReadToEnd();
lxResponseStream.Close();
byte[] lnByte = System.Text.UTF8Encoding.UTF8.GetBytes(lsResponse);
System.IO.FileStream lxFS = new FileStream("34891.jpg", FileMode.Create);
lxFS.Write(lnByte, 0, lnByte.Length);
lxFS.Close();
MessageBox.Show("done");
【问题讨论】:
顺便说一句,您的 HttpWebResponse 和 FileStream 对象需要使用块,因为它们实现了 IDisposable。另外,为什么要初始化 lsResponse,因为它总是会被设置(否则会抛出异常)。最后,我建议你停止使用匈牙利符号(lxFS),你不需要前缀就可以知道每个对象的类型。只需将鼠标悬停在它上面。 【参考方案1】:好图:D
尝试使用以下代码:
您需要使用 BinaryReader,因为图像文件是二进制数据,因此未以 UTF 或 ASCII 编码
编辑:使用'ified
HttpWebRequest lxRequest = (HttpWebRequest)WebRequest.Create(
"http://www.productimageswebsite.com/images/stock_jpgs/34891.jpg");
// returned values are returned as a stream, then read into a string
String lsResponse = string.Empty;
using (HttpWebResponse lxResponse = (HttpWebResponse)lxRequest.GetResponse())
using (BinaryReader reader = new BinaryReader(lxResponse.GetResponseStream()))
Byte[] lnByte = reader.ReadBytes(1 * 1024 * 1024 * 10);
using (FileStream lxFS = new FileStream("34891.jpg", FileMode.Create))
lxFS.Write(lnByte, 0, lnByte.Length);
MessageBox.Show("done");
【讨论】:
-1:我知道您只是在更改他提供的代码,但您应该真正改进它以防止资源泄漏。告诉他在哪里放置using
块,我会删除我的反对票。
我喜欢使用 .Close 方法而不是使用块。根据 msdn: Close 的这种实现调用 Dispose 方法传递一个真值。所以根据资源泄漏我们应该没问题。使用块更安全还是比 .Close() 更有优势? (编辑:忘记关门了)
@henchman:using
块确保 Dispose
将被调用,即使存在未处理的异常。在几乎所有适当的情况下不使用它们是一个坏习惯(您创建一个实现IDisposable
的类的实例,只将它分配给局部变量,并且不要从创建它的方法中返回它,当它是不是 WCF 代理实例)。如果你经常使用它,你不会忘记它一次或两次。
感谢各位的回答。我认为约翰对 using 块的看法是正确的,即使使用 .close 方法也是如此。我认为当变量超出范围时立即进行处理,而不是在例程结束时进行处理。我还认为我将处理例程的 ReadBytes 部分,以分块读取流直到它结束,而不是假定 10MB 的限制。
请告诉我们您针对 10MB 限制的解决方案 - 我找不到这种类型的阅读器/流组合的解决方案。 Stream.Length 不可用。 Using-blocks 也比 .Close() 看起来更好,尽管当更多的块将被聚合到缩进时会很有趣:-)【参考方案2】:
好的,这是最终答案。它使用内存流作为缓冲来自响应流的数据的一种方式。
private void button1_Click(object sender, EventArgs e)
byte[] lnBuffer;
byte[] lnFile;
HttpWebRequest lxRequest = (HttpWebRequest)WebRequest.Create("http://www.productimageswebsite.com/images/stock_jpgs/34891.jpg");
using (HttpWebResponse lxResponse = (HttpWebResponse)lxRequest.GetResponse())
using (BinaryReader lxBR = new BinaryReader(lxResponse.GetResponseStream()))
using (MemoryStream lxMS = new MemoryStream())
lnBuffer = lxBR.ReadBytes(1024);
while (lnBuffer.Length > 0)
lxMS.Write(lnBuffer, 0, lnBuffer.Length);
lnBuffer = lxBR.ReadBytes(1024);
lnFile = new byte[(int)lxMS.Length];
lxMS.Position = 0;
lxMS.Read(lnFile, 0, lnFile.Length);
using (System.IO.FileStream lxFS = new FileStream("34891.jpg", FileMode.Create))
lxFS.Write(lnFile, 0, lnFile.Length);
MessageBox.Show("done");
【讨论】:
哦,是的...忘记删除 close 方法,因为我正在使用 using 块。【参考方案3】:答案的变体,使用 async await 异步文件 I/O。 See Async File I/O 为什么这很重要。
下载 png 并使用 BinaryReader/Writer 写入磁盘
string outFile = System.IO.Path.Combine(outDir, fileName);
// Download file
var request = (HttpWebRequest) WebRequest.Create(imageUrl);
using (var response = await request.GetResponseAsync())
using (var reader = new BinaryReader(response.GetResponseStream()))
// Read file
Byte[] bytes = async reader.ReadAllBytes();
// Write to local folder
using (var fs = new FileStream(outFile, FileMode.Create))
await fs.WriteAsync(bytes, 0, bytes.Length);
读取所有字节扩展方法
public static class Extensions
public static async Task<byte[]> ReadAllBytes(this BinaryReader reader)
const int bufferSize = 4096;
using (var ms = new MemoryStream())
byte[] buffer = new byte[bufferSize];
int count;
while ((count = reader.Read(buffer, 0, buffer.Length)) != 0)
await ms.WriteAsync(buffer, 0, count);
return ms.ToArray();
【讨论】:
【参考方案4】:您可以使用以下方法从网站下载图像并使用 Image 类进行保存:
WebRequest req = WebRequest.Create(imageUrl);
WebResponse resp = req.GetResponse();
Image img = Image.FromStream(resp.GetResponseStream());
img.Save(filePath + fileName + ".jpg");
【讨论】:
以上是关于如何使用 httpwebrequest 将图像从网站拉到本地文件的主要内容,如果未能解决你的问题,请参考以下文章
上传Image MultiPart Form HTTPWebRequest - 将图像数据转换为字符串?
如何使用 HttpWebRequest 将数据发布到 MVC 控制器?