This is a read-only snapshot of the ComputerCraft forums, taken in April 2020.
gob's profile picture

How do I download a binary file?

Started by gob, 03 December 2012 - 05:24 AM
gob #1
Posted 03 December 2012 - 06:24 AM
I'm trying to download a binary file from a website into the game.

This is a snippet of the code I'm trying to use:


local response = http.get("https://www.google.com/images/srpr/logo3w.png")
if response then
   local sRespons = response.readAll()
   response.close()
   local file = fs.open ("file.png", "wb" )
   file.write ( sRespons )
   file.close()
end

The part that doesn't work is "wb". If i leave it as "w" it downloads and saves the file as text. When I have it as "wb" I get the error: "bad argument: number expected, got string" at that line and it just saves a blank file.
Kingdaro #2
Posted 03 December 2012 - 06:32 AM
You should probably use tonumber() to convert sRespons before writing it.
Lyqyd #3
Posted 03 December 2012 - 07:17 AM
You'll want to check out either string.char or string.byte, as you'll need to write the entire file one byte at a time.
ChunLing #4
Posted 03 December 2012 - 10:06 AM
I don't think that you should try "local sRespons = response.readAll()" Let response talk directly to file, they're both tables with similar methods available to them.

At the very least, play around with sRespons some more, find out exactly what you can do with the data it contains.

Too bad that "wb" doesn't work. It should, according to the wiki.
Lyqyd #5
Posted 03 December 2012 - 02:33 PM
I don't think that you should try "local sRespons = response.readAll()" Let response talk directly to file, they're both tables with similar methods available to them.

At the very least, play around with sRespons some more, find out exactly what you can do with the data it contains.

Too bad that "wb" doesn't work. It should, according to the wiki.

That's not at all what the problem is. The problem is that when writing in binary mode, one must call handle.write() for each byte in the file, and pass that byte in as a number. They will need to use string.byte or string.char (I think the former, but cannot recall exactly) to get the numeric value of each character (byte) in the string.
ChunLing #6
Posted 04 December 2012 - 09:14 AM
Oh, I see. So it was "file.write ( sRespons ) " that failed rather than local file = fs.open ("file.png", "wb" ). gob didn't make that very clear.

I still think that it makes more sense to keep response open and use response.read() to get the data as a series of numbers to feed into file.write() rather than grab the whole thing with readAll.
gob #7
Posted 04 December 2012 - 09:39 PM
Oh, I see. So it was "file.write ( sRespons ) " that failed rather than local file = fs.open ("file.png", "wb" ). gob didn't make that very clear.

I still think that it makes more sense to keep response open and use response.read() to get the data as a series of numbers to feed into file.write() rather than grab the whole thing with readAll.
yeah I said it was that line but I was wrong about that. Was editing the code in the game and got the line number wrong.
ChunLing #8
Posted 05 December 2012 - 10:12 AM
Is response.read() an available method? Does response.read() give you an integer? Can you use that integer in file.write()?
MysticT #9
Posted 05 December 2012 - 12:09 PM
Try writing each byte in the string to the file (like suggested above), like this:

local response = http.get("https://www.google.com/images/srpr/logo3w.png")
if response then
  local sResponse = response.readAll()
  response.close()
  local file = fs.open("file.png", "wb")
  for i = 1, #sResponse do
    file.write(string.byte(sResponse, i))
  end
  file.close()
end