[downloader/fragment] Use temp file for current fragment

This commit is contained in:
Sergey M․ 2017-04-24 02:54:17 +07:00
parent a4d6cf970c
commit d3f0687cf7
No known key found for this signature in database
GPG Key ID: 2C393E0F18A9236D
2 changed files with 41 additions and 26 deletions

View File

@ -2,7 +2,6 @@ from __future__ import division, unicode_literals
import os import os
import time import time
import io
import json import json
from .common import FileDownloader from .common import FileDownloader
@ -48,28 +47,42 @@ class FragmentFD(FileDownloader):
self._prepare_frag_download(ctx) self._prepare_frag_download(ctx)
self._start_frag_download(ctx) self._start_frag_download(ctx)
def _read_ytdl_file(self, ctx):
stream, _ = sanitize_open(self.ytdl_filename(ctx['filename']), 'r')
ctx['fragment_index'] = json.loads(stream.read())['download']['current_fragment_index']
stream.close()
def _write_ytdl_file(self, ctx):
frag_index_stream, _ = sanitize_open(self.ytdl_filename(ctx['filename']), 'w')
frag_index_stream.write(json.dumps({
'download': {
'current_fragment_index': ctx['fragment_index']
},
}))
frag_index_stream.close()
def _download_fragment(self, ctx, frag_url, info_dict, headers=None): def _download_fragment(self, ctx, frag_url, info_dict, headers=None):
down = io.BytesIO() fragment_filename = '%s-Frag%d' % (ctx['tmpfilename'], ctx['fragment_index'])
success = ctx['dl'].download(down, { success = ctx['dl'].download(fragment_filename, {
'url': frag_url, 'url': frag_url,
'http_headers': headers or info_dict.get('http_headers'), 'http_headers': headers or info_dict.get('http_headers'),
}) })
if not success: if not success:
return False, None return False, None
frag_content = down.getvalue() down, frag_sanitized = sanitize_open(fragment_filename, 'rb')
ctx['fragment_filename_sanitized'] = frag_sanitized
frag_content = down.read()
down.close() down.close()
return True, frag_content return True, frag_content
def _append_fragment(self, ctx, frag_content): def _append_fragment(self, ctx, frag_content):
try:
ctx['dest_stream'].write(frag_content) ctx['dest_stream'].write(frag_content)
finally:
if not (ctx.get('live') or ctx['tmpfilename'] == '-'): if not (ctx.get('live') or ctx['tmpfilename'] == '-'):
frag_index_stream, _ = sanitize_open(self.ytdl_filename(ctx['filename']), 'w') self._write_ytdl_file(ctx)
frag_index_stream.write(json.dumps({ os.remove(ctx['fragment_filename_sanitized'])
'download': { del ctx['fragment_filename_sanitized']
'last_fragment_index': ctx['fragment_index']
},
}))
frag_index_stream.close()
def _prepare_frag_download(self, ctx): def _prepare_frag_download(self, ctx):
if 'live' not in ctx: if 'live' not in ctx:
@ -93,23 +106,29 @@ class FragmentFD(FileDownloader):
tmpfilename = self.temp_name(ctx['filename']) tmpfilename = self.temp_name(ctx['filename'])
open_mode = 'wb' open_mode = 'wb'
resume_len = 0 resume_len = 0
frag_index = 0
# Establish possible resume length # Establish possible resume length
if os.path.isfile(encodeFilename(tmpfilename)): if os.path.isfile(encodeFilename(tmpfilename)):
open_mode = 'ab' open_mode = 'ab'
resume_len = os.path.getsize(encodeFilename(tmpfilename)) resume_len = os.path.getsize(encodeFilename(tmpfilename))
ytdl_filename = encodeFilename(self.ytdl_filename(ctx['filename']))
if os.path.isfile(ytdl_filename): ctx['fragment_index'] = 0
frag_index_stream, _ = sanitize_open(ytdl_filename, 'r') if os.path.isfile(encodeFilename(self.ytdl_filename(ctx['filename']))):
frag_index = json.loads(frag_index_stream.read())['download']['last_fragment_index'] self._read_ytdl_file(ctx)
frag_index_stream.close() else:
self._write_ytdl_file(ctx)
if ctx['fragment_index'] > 0:
assert resume_len > 0
else:
assert resume_len == 0
dest_stream, tmpfilename = sanitize_open(tmpfilename, open_mode) dest_stream, tmpfilename = sanitize_open(tmpfilename, open_mode)
ctx.update({ ctx.update({
'dl': dl, 'dl': dl,
'dest_stream': dest_stream, 'dest_stream': dest_stream,
'tmpfilename': tmpfilename, 'tmpfilename': tmpfilename,
'fragment_index': frag_index,
# Total complete fragments downloaded so far in bytes # Total complete fragments downloaded so far in bytes
'complete_frags_downloaded_bytes': resume_len, 'complete_frags_downloaded_bytes': resume_len,
}) })

View File

@ -20,14 +20,10 @@ from ..utils import (
class HttpFD(FileDownloader): class HttpFD(FileDownloader):
def real_download(self, filename_or_stream, info_dict): def real_download(self, filename, info_dict):
url = info_dict['url'] url = info_dict['url']
filename = filename_or_stream
stream = None
if hasattr(filename_or_stream, 'write'):
stream = filename_or_stream
filename = '-'
tmpfilename = self.temp_name(filename) tmpfilename = self.temp_name(filename)
stream = None
# Do not include the Accept-Encoding header # Do not include the Accept-Encoding header
headers = {'Youtubedl-no-compression': 'True'} headers = {'Youtubedl-no-compression': 'True'}