Skip to content

Commit c80fa05

Browse files
Add chunk_callback to download_url()
1 parent 0977ab2 commit c80fa05

File tree

1 file changed

+48
-21
lines changed
  • internal_filesystem/builtin/apps/com.micropythonos.appstore/assets

1 file changed

+48
-21
lines changed

internal_filesystem/builtin/apps/com.micropythonos.appstore/assets/appstore.py

Lines changed: 48 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -177,62 +177,89 @@ def show_app_detail(self, app):
177177
intent.putExtra("appstore", self)
178178
self.startActivity(intent)
179179

180-
async def download_url(self, url, outfile=None, total_size=None, progress_callback=None):
180+
'''
181+
This async download function can be used in 3 ways:
182+
- with just a url => returns the content
183+
- with a url and an outfile => writes the content to the outfile
184+
- with a url and a chunk_callback => calls the chunk_callback(chunk_data) for each chunk
185+
186+
Optionally:
187+
- progress_callback is called with the % (0-100) progress
188+
- if total_size is not provided, it will be taken from the response headers (if present) or default to 100KB
189+
190+
Can return either:
191+
- the actual content
192+
- None: if the content failed to download
193+
- True: if the URL was successfully downloaded (and written to outfile, if provided)
194+
- False: if the URL was not successfully download and written to outfile
195+
'''
196+
async def download_url(self, url, outfile=None, total_size=None, progress_callback=None, chunk_callback=None):
181197
print(f"Downloading {url}")
182198
#await TaskManager.sleep(4) # test slowness
183199
try:
184200
async with self.aiohttp_session.get(url) as response:
185201
if response.status < 200 or response.status >= 400:
186202
return False if outfile else None
187203

188-
# Always use chunked downloading
189-
chunk_size = 1024
204+
# Figure out total size
190205
print("headers:") ; print(response.headers)
191206
if total_size is None:
192207
total_size = response.headers.get('Content-Length') # some servers don't send this in the headers
193-
print(f"download_url {'writing to ' + outfile if outfile else 'reading'} {total_size} bytes in chunks of size {chunk_size}")
194-
195-
fd = open(outfile, 'wb') if outfile else None
196-
chunks = [] if not outfile else None
208+
if total_size is None:
209+
print("WARNING: Unable to determine total_size from server's reply and function arguments, assuming 100KB")
210+
total_size = 100 * 1024
211+
212+
fd = None
213+
if outfile:
214+
fd = open(outfile, 'wb')
215+
if not fd:
216+
print("WARNING: could not open {outfile} for writing!")
217+
return False
218+
chunks = []
197219
partial_size = 0
220+
chunk_size = 1024
198221

199-
if fd:
200-
print("opened file...")
222+
print(f"download_url {'writing to ' + outfile if outfile else 'downloading'} {total_size} bytes in chunks of size {chunk_size}")
201223

202224
while True:
203225
tries_left = 3
204-
chunk = None
226+
chunk_data = None
205227
while tries_left > 0:
206228
try:
207-
chunk = await TaskManager.wait_for(response.content.read(chunk_size), 10)
229+
chunk_data = await TaskManager.wait_for(response.content.read(chunk_size), 10)
208230
break
209231
except Exception as e:
210-
print(f"Waiting for response.content.read of next chunk got error: {e}")
232+
print(f"Waiting for response.content.read of next chunk_data got error: {e}")
211233
tries_left -= 1
212234

213235
if tries_left == 0:
214-
print("ERROR: failed to download chunk, even with retries!")
236+
print("ERROR: failed to download chunk_data, even with retries!")
215237
if fd:
216238
fd.close()
217239
return False if outfile else None
218240

219-
if chunk:
220-
partial_size += len(chunk)
241+
if chunk_data:
242+
# Output
243+
if fd:
244+
fd.write(chunk_data)
245+
elif chunk_callback:
246+
await chunk_callback(chunk_data)
247+
else:
248+
chunks.append(chunk_data)
249+
# Report progress
250+
partial_size += len(chunk_data)
221251
progress_pct = round((partial_size * 100) / int(total_size))
222252
print(f"progress: {partial_size} / {total_size} bytes = {progress_pct}%")
223253
if progress_callback:
224254
await progress_callback(progress_pct)
225255
#await TaskManager.sleep(1) # test slowness
226-
if fd:
227-
fd.write(chunk)
228-
else:
229-
chunks.append(chunk)
230256
else:
231-
print("chunk is None while there was no error so this was the last one")
232-
print(f"Done downloading {url}")
257+
print("chunk_data is None while there was no error so this was the last one.\n Finished downloading {url}")
233258
if fd:
234259
fd.close()
235260
return True
261+
elif chunk_callback:
262+
return True
236263
else:
237264
return b''.join(chunks)
238265
except Exception as e:

0 commit comments

Comments
 (0)