def download(self) -> str:
if self._state != NOT_STARTED:
return self._state
# Prepare an empty buffer file.
await self._loop.run_in_executor(None, self._create_buffer_file)
try:
# Create client session for downloading a file part from a host.
async with aiohttp.ClientSession(loop=self._loop, headers=self._headers) as session:
# Request a host for a file part.
async with session.request('GET', self._url) as res: # type: aiohttp.ClientResponse
if res.status != 206:
raise WrongResponseError('Expected status code 206, but {!s} ({!s}) received.',
res.status,
res.reason)
hrh = res.headers # type: CIMultiDictProxy
# TODO: check headers.
# Read content by chunks and write to the buffer file.
if self._state == NOT_STARTED:
self._state = DOWNLOADING
while self._state is DOWNLOADING:
with aiohttp.Timeout(self._chunk_download_timeout, loop=self._loop):
chunk = await res.content.read(self._chunk_size)
self._bytes_downloaded += len(chunk)
self._debug("Read ({!s} bytes). Downloaded: {!s} of {!s} bytes. [{:.2%}]".format(
len(chunk), self._bytes_downloaded, self._length,
self._bytes_downloaded / self._length))
if not chunk:
self._state = DOWNLOADED
break
await self._write_chunk(chunk)
await self._flush_and_release()
if self._state != DOWNLOADED:
res.close() # Close the response if not downloaded.
except aiohttp.ServerDisconnectedError as exc:
self._debug('Server disconnected error: {!r}.'.format(exc))
self.cancel()
except WrongResponseError as exc:
self._debug('Wrong response error: {!r}.'.format(exc))
self.cancel()
except asyncio.TimeoutError:
self._debug('Timeout.')
self.cancel()
except Exception as exc:
self._debug('Unexpected exception: {!r}.'.format(exc))
self.cancel()
finally:
return self._state
评论列表
文章目录