HTTPDownloader.py :  » RSS » PenguinTV » PenguinTV-4.1.0 » penguintv » Python Open Source

Home
Python Open Source
1.3.1.2 Python
2.Ajax
3.Aspect Oriented
4.Blog
5.Build
6.Business Application
7.Chart Report
8.Content Management Systems
9.Cryptographic
10.Database
11.Development
12.Editor
13.Email
14.ERP
15.Game 2D 3D
16.GIS
17.GUI
18.IDE
19.Installer
20.IRC
21.Issue Tracker
22.Language Interface
23.Log
24.Math
25.Media Sound Audio
26.Mobile
27.Network
28.Parser
29.PDF
30.Project Management
31.RSS
32.Search
33.Security
34.Template Engines
35.Test
36.UML
37.USB Serial
38.Web Frameworks
39.Web Server
40.Web Services
41.Web Unit
42.Wiki
43.Windows
44.XML
Python Open Source » RSS » PenguinTV 
PenguinTV » PenguinTV 4.1.0 » penguintv » HTTPDownloader.py
import logging
import time

from Downloader import *

import ptvDB
import pycurl
import utils
import os
#import time
import MediaManager


#Downloader API:
#constructor takes:  media, params, resume, queue, progress_callback, finished_callback
#  media:  the media dic
#  params: optional params, like for btdownloader
#  resume: are we supposed to resume?
#  queue:  are we supposed queue for playback when download is finished?  this variable is just passed around
#  progress_callback:  function to call for progress update.
#          arg of this is: (media, progress as 0 < x < 1, and text formatted message of progress)
#          the callback will return 1 if we should cancel download
#  finished_callback:  function to call when finished.
#          args is: (media, status, message)
#              where status is 0=failed, 1=success, 2=success and queue

class HTTPDownloader(Downloader):
  """Need a little internal class to keep track of callbacks from urllib.urlretrieve"""
  def __init__(self, media, media_dir, params, resume, queue, progress_callback, finished_callback):
    Downloader.__init__(self, media, media_dir, params, resume, queue, progress_callback, finished_callback)
    #no params
    self._resume_from = 0
    self._last_progress = 0
    
  def download(self,args_unused):
    if not Downloader.download(self,args_unused):
      #stopped before we began, no callback
      return
    try:
      os.makedirs(os.path.dirname(self.media['file']))
    except OSError:
      pass
    try:
      if self._resume:
        try:
          fp = open(self.media['file'], "ab")
        except:
          fp = open(self.media['file'], "wb")
      else:
        fp = open(self.media['file'], "wb")
      curl = pycurl.Curl()
      curl.setopt(pycurl.URL, str(self.media['url']).strip()) #cause it's unicode or some shit which is not a string or some junk.  Also strip whitespace
      curl.setopt(pycurl.FOLLOWLOCATION, 1)
      curl.setopt(pycurl.MAXREDIRS, 5)
      curl.setopt(pycurl.CONNECTTIMEOUT, 30)
      curl.setopt(pycurl.NOSIGNAL, 1) #makes downloading thread-safe
      curl.setopt(pycurl.WRITEDATA, fp)
      curl.setopt(pycurl.PROGRESSFUNCTION, self._wrap_progress_callback)
      curl.setopt(pycurl.NOPROGRESS, 0)
      curl.setopt(pycurl.USERAGENT,'PenguinTV '+utils.VERSION)
      if self._resume:
        self._resume_from = os.stat(self.media['file'])[6]
        curl.setopt(pycurl.RESUME_FROM_LARGE, self._resume_from)
      curl.perform()
      response = curl.getinfo(pycurl.RESPONSE_CODE)
      curl.close()
      fp.close()
      if self.media['url'][:5] == "http:":
        if response != 200 and response != 206:
          logging.warning("HTTP download error: %s" % response)
          if response == 404:
            self.media['errormsg']=_("404: File Not Found")
          elif response == 400:
            #maybe not properly escaped url?
            import urlparse, urllib
            p = urlparse.urlparse(self.media['url'])
            new_p = (p[0], urllib.quote(p[1]), urllib.quote(p[2]),
              urllib.quote(p[3]), urllib.quote(p[4]), urllib.quote(p[5]))
            new_url = urlparse.urlunparse(new_p)
            self.media['url'] = new_url
            self.download(None)
            return
          else:
            d = {"response":response}
            self.media['errormsg']=_("Some HTTP error: %(response)s") % d
          self.status = FAILURE
          self.message = self.media['errormsg']
          self._finished_callback()
          return
      elif self.media['url'][:5] == "file:":
        pass #it's ok, curl would throw an exception on error
      elif self.media['url'][:4] == "ftp:":
        major_code = response / 100
        if major_code == 2: #positive reply
          pass
        elif major_code == 4 or major_code == 5:
          d = {"response":response}
          self.media['errormsg']=_("FTP error: %(response)s") % d
        else:
          d = {"response":response}
          self.media['errormsg']=_("Unexpected FTP response: %(response)s") % d
      else: 
        self.media['errormsg']=_("Unknown protocol")
        self.status = FAILURE
        self.message = self.media['errormsg']
        self._finished_callback()
        return
      
      if self._queue:
        self.status = FINISHED_AND_PLAY
        self.message = _("finished downloading %s") % self.media['file']
        self._finished_callback()
        return
      self.status = FINISHED
      self.message = _("finished downloading %s") % self.media['file']
      self._finished_callback()
    except Exception, data: #this can happen if we cancelled the download
      if data[0]==33: #if server doesn't support resuming, retry
        self._resume=False
        self.download(None)
      elif data[0]==42:
        if self.status not in [STOPPED, PAUSED]:
          self.status = STOPPED
        self.message = ""
        self._finished_callback()
      else:
        logging.warning("some downloading error %s %s" % (str(data),self.media))
        self.media['errormsg']=data
        self.status = FAILURE
        self.message = data
        self._finished_callback()
    
  def _wrap_progress_callback(self, dl_total, dl_now, ul_total, ul_now):
    now = time.time()
    if now - self._last_progress < 2.0:
      return
    self._last_progress = now
    if self._resume: #adjust sizes so that the percentages are correct
      dl_total += self._resume_from
      dl_now   += self._resume_from
    try:
      self.progress = int((dl_now*100.0)/dl_total)
    except:
      self.progress = 0  
    if not self.media.has_key('size'):
      self.media['size_adjustment']=True
    elif self.media['size']!=round(dl_total) and not self._resume:
      self.media['size']=round(dl_total)
      self.media['size_adjustment']=True
    else:
      self.media['size_adjustment']=False
    d = { 'progress': str(self.progress),
        'size': utils.format_size(self.media['size'])}
    self.total_size = self.media['size']
    if self.total_size == 0:
      d['dl_now'] = dl_now
      self.message = _("Downloaded %(dl_now)s...") % d
    else:
      self.message = _("Downloaded %(progress)s%% of %(size)s") % d
    return self._progress_callback()
www.java2java.com | Contact Us
Copyright 2009 - 12 Demo Source and Support. All rights reserved.
All other trademarks are property of their respective owners.