Downloading multiple images

I have a list of file id’s of images in my drive that I put into a link to download, I’m trying to download all of them to the document directory and save their names in a table to be accessed later. 

My problem is, while it downloads, it runs other commands but I want it to wait until it downloads all the images before moving forward. I can’t use sockets cause sockets don’t work with “GET”. Here’s my code so far:

if event.response then local decodedResponse = json.decode(event.response) local slideImages={} local function networkListener( event ) if ( event.isError ) then print( "Network error - download failed: ", event.response ) elseif ( event.phase == "began" ) then print( "Progress Phase: began" ) elseif ( event.phase == "ended" ) then print( "downloaded" ) table.insert( slideImages, event.response.filename ) end end for i = 1, #decodedResponse.files do local params = {} params.progress = true network.download( "https://drive.google.com/uc?export=download&id="..decodedResponse.files[i].id, "GET", networkListener, params, decodedResponse.files[i].name, system.DocumentsDirectory ) end goToNextScene()

The code calls the “goToNextScene()” before all images are downloading and it causes and error.

I’d appreciate the helps thanks! 

I know a solution would be to call the next download from the listener but I can’t figure out how to do this and stop it from moving forward.

You need to write a sequential downloader.

If you know the file names in advance you do this:

-- -- This is pseudo code -- local next local onComplete local onFailure -- You must handle failed downloads some how... local listener local slideImages = {} local index = 0 local list { "url1", "ulr2", ... "ulrN", } local saveAs { "name1", "name2", ... "nameN", } listener = function( event ) if ( event.isError ) then onFailure() -- elseif ( event.phase == "ended" ) then table.insert( slideImages, event.response.filename ) next() end end onComplete = function() goToNextScene() end next = function() index = index + 1 if( index \> #list ) then onComplete() -- Done! return end local params = {} params.progress = true network.download( list[index], "GET", listener, params, saveAs[index], system.DocumentsDirectory) end next()

If you are getting the file names from your queries, then you need to do something similar, but instead of a table of urls and save names, you keep a variable that contains the ‘next’ file to download and when you have no more set it to nil.  Then, the next() code will see this and assume you’re done, thus calling onComplete()

Essentially what you need to do is:

  • Break up the steps into individual helper functions.
  • Forward declare them (because they ‘cross-call’ each other; so there is no order you can directly declare and define them in that will work scope-wise.)
  • Define them.
  • Run the function that starts the process.

You must know what forward declaration is to understand this.

Thanks, this looks like it would work great :slight_smile:

Your code does what I asked, which is fantastic, though now the images it downloads are invalid >.>

Check your code for typos and naming issues.  Sequential downloads won’t cause issues with downloaded files.

If you’re doing this in the simulator you can inspect the files directly in the Sandbox.

You were right, seems there’s something wrong with my drive, it’s showing files that aren’t there. Thanks for the help again!

Check the file paths you’re saving to by printing them in the listener to verify the path is full and correct.

I managed to fix the drive issue and went over the code but the images downloaded are still invalid, in the sandbox, a thumbnail doesn’t show like it normally would and i can’t preview the image.

What do you mean print the path?

okay, i got the path to print out and everything seems fine

Nevermind.  If you have downloaded the files then the path doesn’t matter any more.

I don’t know what to tell you.  

Give an example of a URL for one of these images so I can download it and look at the image.

So is this working now or you are your images still corrupt?

The path seems fine but the images are still corrupt

Here’s a sample url of one of the images:

https://drive.google.com/uc?export=download&id=0BwDQJtfQLhMGbUFQUU1GWnFMSW8

it’s what i was using with my previous solution, the previous one downloaded fine though, there isn’t much change so I’m not sure why it’s not working now

That isn’t a valid link and it really looks weird to me.  I don’t think you can rely on it working forever. 

  1. A normal link would have the actual file name and extension.

  2. That looks like it could be time-stamped to only last for a while then become invalid.

  3. Whatever the case, when I go to: https://drive.google.com/uc?export=download&id=0BwDQJtfQLhMGbUFQUU1GWnFMSW8

I get a 403 error. - No access to page.

Please share a link that works in a browser that anyone can download.

That said, I think you’ll probably have to work this out or hire help or get a mentor to help.

I’m out of ideas.  The fundamentals are correct, but I’m not sure what wrenches that URL scheme is throwing into the works.

That’s okay, I appreciate the help so far, looks like I’ll have to figure this one out on my own >.>

thanks for all the help!

You need to write a sequential downloader.

If you know the file names in advance you do this:

-- -- This is pseudo code -- local next local onComplete local onFailure -- You must handle failed downloads some how... local listener local slideImages = {} local index = 0 local list { "url1", "ulr2", ... "ulrN", } local saveAs { "name1", "name2", ... "nameN", } listener = function( event ) if ( event.isError ) then onFailure() -- elseif ( event.phase == "ended" ) then table.insert( slideImages, event.response.filename ) next() end end onComplete = function() goToNextScene() end next = function() index = index + 1 if( index \> #list ) then onComplete() -- Done! return end local params = {} params.progress = true network.download( list[index], "GET", listener, params, saveAs[index], system.DocumentsDirectory) end next()

If you are getting the file names from your queries, then you need to do something similar, but instead of a table of urls and save names, you keep a variable that contains the ‘next’ file to download and when you have no more set it to nil.  Then, the next() code will see this and assume you’re done, thus calling onComplete()

Essentially what you need to do is:

  • Break up the steps into individual helper functions.
  • Forward declare them (because they ‘cross-call’ each other; so there is no order you can directly declare and define them in that will work scope-wise.)
  • Define them.
  • Run the function that starts the process.

You must know what forward declaration is to understand this.

Thanks, this looks like it would work great :slight_smile:

Your code does what I asked, which is fantastic, though now the images it downloads are invalid >.>