Is is possible to programmaticaly save a graphic forma given URL?

  • Thread starter Thread starter Stacey Levine
  • Start date Start date
S

Stacey Levine

Ok.. Maybe I am trying the wrong approach. If given a URL to a graphic, I
want to save that graphic to a local file. The approach below gets the
response, but I can't quite figure out how to save it to a file. In this
instance, a file gets created but it only contains the text
"System.Io.StreamReader" I have also tried writer.write(reader.ReadToEnd),
but the file still displays nothing.


Dim URL As String = GraphicURL

Dim request As WebRequest = WebRequest.Create(URL)

Dim response As WebResponse = request.GetResponse()

Dim reader As StreamReader = New

StreamReader(response.GetResponseStream())

Dim writer As StreamWriter = New StreamWriter("C:\temp\" & GraphicKey &
".jpg")

writer.Write(reader)

writer.Close()

reader.Close()

response.Close()


Stacey Levine
 
Yes, you are writing the reader, rather than writing what the reader is
reading :) Try writing reader.readtoend (or something).
 
I did try writer.write(reader.ReadToEnd), and the file has more data.. it
is all hex.. but it still won't open as a picture. I am not sure if I missed
writing something.
 
One other wierd bit.. when I save the file using the reader.ReadToEnd ..
the file has 1302 bytes.
If I right click the image and save it, it has 2257 bytes.

very very wierd
 
Try BinaryWriter/BinaryReader:

Try
Dim Request As HttpWebRequest =
HttpWebRequest.Create(http://i3.microsoft.com/h/en-us/i/SpeedPC_2_10.jpg)
Request.Timeout = 5000
Dim Response As HttpWebResponse = Request.GetResponse()
Dim myReader As BinaryReader
myReader = New BinaryReader(Response.GetResponseStream())
Dim Result() As Byte = myReader.ReadBytes(Response.ContentLength)
Dim myFileStream As New FileStream("c:\SpeedPC_2_10.jpg",
FileMode.CreateNew)
Dim myWriter As New BinaryWriter(myFileStream)
myWriter.Write(Result)
myWriter.Close()
Catch e As Exception
MessageBox.Show(e.Message, "Error Occurred")
End Try
 
You're using a regular StreamReader and StreamWriter, so it's using Default
Text encodings. You need to use BinaryReader/BinaryWriter for Binary
graphic data. See other post.
 
Stacey Levine said:
Ok.. Maybe I am trying the wrong approach. If given a URL to a graphic, I
want to save that graphic to a local file. The approach below gets the
response, but I can't quite figure out how to save it to a file.

Check out 'WebClient.DownloadFile'.
 
Stacey,
In addition to the other comments:

Don't use StreamReader & StreamWriter on binary files (such as graphic
files), as StreamReader & StreamWriter are used with Text Files.

If you simply want to copy the file, I would not even bother with
BinaryReader & BinaryWriter, as StreamReader & StreamWriter and BinaryReader
& BinaryWriter are used to parse "formatted" files, you simply want to copy
the bytes.

The "easiest" way is to use WebClient.DownloadFile as Herfried shows.
Alternatively you can use a loop, something like:

Dim URL As String = GraphicURL
Dim request As WebRequest = WebRequest.Create(URL)
Dim response As WebResponse = request.GetResponse()

Dim input As Stream = response.GetResponseStream()
Dim output As New FileStream("C:\temp\" & graphicKey & ".jpg",
FileMode.Create)

Dim count As Integer = 32 * 1024
Dim buffer(count - 1) As Byte

Do
count = input.Read(buffer, 0, count)
If count = 0 Then Exit Do
output.Write(buffer, 0, count)
Loop

input.Close()
output.Close()
response.Close()

Hope this helps
Jay

| Ok.. Maybe I am trying the wrong approach. If given a URL to a graphic, I
| want to save that graphic to a local file. The approach below gets the
| response, but I can't quite figure out how to save it to a file. In this
| instance, a file gets created but it only contains the text
| "System.Io.StreamReader" I have also tried writer.write(reader.ReadToEnd),
| but the file still displays nothing.
|
|
| Dim URL As String = GraphicURL
|
| Dim request As WebRequest = WebRequest.Create(URL)
|
| Dim response As WebResponse = request.GetResponse()
|
| Dim reader As StreamReader = New
|
| StreamReader(response.GetResponseStream())
|
| Dim writer As StreamWriter = New StreamWriter("C:\temp\" & GraphicKey &
| ".jpg")
|
| writer.Write(reader)
|
| writer.Close()
|
| reader.Close()
|
| response.Close()
|
|
| Stacey Levine
|
|
 
Alternatively, you can eliminate the "loop" and all the extra logic and code
(Dim count, Dim buffer(count - 1), If...Then..Exit Do, etc.) by using the
BinaryReader's .ReadBytes() method in conjunction with the BinaryWriter's
ability to write an entire Byte array to a file at once. I.e.,

'...
Dim Result() As Byte = myReader.ReadBytes(Response.ContentLength)
'...
myWriter.Write(Result)
'...
 
The data returned is probably gzip'ed(documented in RFC1950 to RFC 1952),
you dont want to read the HTTP data as GZIP if you dont intend to unzip it
programatically.
 
Michael,
| Alternatively, you can eliminate the "loop" and all the extra logic and
code
| (Dim count, Dim buffer(count - 1), If...Then..Exit Do, etc.) by using the
You can do that, but I would question if you should do that! ;-)

What happens when you download a 1600 x 1200 32bit color TIFF?

Allocating such a large single block of memory may cause undue stress on the
GC & the memory requirements of your app.

A 1600 x 1200 32bit color TIFF is 5M, while the corresponding JPG is .9M
both of which seems to be an excessive size to allocate a single block.
Especially if the OP is going to be processing multiple files at a time...
Ergo my loop example. Granted the size of the buffer in the loop makes a
difference, I picked 32K, which may be too small. One should really pick a
size that exceeds most of the files involved, yet does not cause undue
stress on memory & the GC. In other words 64K or 128K might be a better
buffer, although I understand a 128K buffer would be placed in the large
memory heap which might not be a good idea...

Just a thought
Jay


| Alternatively, you can eliminate the "loop" and all the extra logic and
code
| (Dim count, Dim buffer(count - 1), If...Then..Exit Do, etc.) by using the
| BinaryReader's .ReadBytes() method in conjunction with the BinaryWriter's
| ability to write an entire Byte array to a file at once. I.e.,
|
| '...
| Dim Result() As Byte = myReader.ReadBytes(Response.ContentLength)
| '...
| myWriter.Write(Result)
| '...
|
| | > Alternatively you can use a loop, something like:
| >
| > Dim URL As String = GraphicURL
| > Dim request As WebRequest = WebRequest.Create(URL)
| > Dim response As WebResponse = request.GetResponse()
| >
| > Dim input As Stream = response.GetResponseStream()
| > Dim output As New FileStream("C:\temp\" & graphicKey & ".jpg",
| > FileMode.Create)
| >
| > Dim count As Integer = 32 * 1024
| > Dim buffer(count - 1) As Byte
| >
| > Do
| > count = input.Read(buffer, 0, count)
| > If count = 0 Then Exit Do
| > output.Write(buffer, 0, count)
| > Loop
| >
| > input.Close()
| > output.Close()
| > response.Close()
| >
|
|
 
The "easiest" way is to use WebClient.DownloadFile as Herfried shows.

And extremely fast way,

And if needed a progressbar, because of slow connections. Than Jay's method
because that is the negative point from "DownloadFile" that you can AFAIK
not use that with it.

:-)

Cor
 
Back
Top