From: Calin Crisan <ccrisan@gmail.com> Date: Thu, 8 Jun 2017 19:46:34 +0000 (+0300) Subject: add support for uploading to ftp server X-Git-Url: http://www.vanbest.org/gitweb/?a=commitdiff_plain;h=296c29714ce2ab8deb0c9461b074ef39493b770a;p=motioneye-debian add support for uploading to ftp server --- diff --git a/motioneye/mjpgclient.py b/motioneye/mjpgclient.py index ecd4a05..dc9c656 100644 --- a/motioneye/mjpgclient.py +++ b/motioneye/mjpgclient.py @@ -279,8 +279,6 @@ def close_all(invalidate=False): def _garbage_collector(): - logging.debug('running garbage collector for mjpg clients...') - io_loop = IOLoop.instance() io_loop.add_timeout(datetime.timedelta(seconds=settings.MJPG_CLIENT_TIMEOUT), _garbage_collector) diff --git a/motioneye/templates/main.html b/motioneye/templates/main.html index 5292ae2..085ac74 100644 --- a/motioneye/templates/main.html +++ b/motioneye/templates/main.html @@ -423,7 +423,7 @@ <td class="settings-item-label"><span class="settings-item-label">Upload Service</span></td> <td class="settings-item-value"> <select class="styled storage camera-config" id="uploadServiceSelect"> -<!-- <option value="ftp">FTP Server</option> --> + <option value="ftp">FTP Server</option> <!-- <option value="sftp">SFTP Server</option> --> <!-- <option value="http">HTTP Server</option> --> <!-- <option value="https">HTTPS Server</option> --> diff --git a/motioneye/uploadservices.py b/motioneye/uploadservices.py index c389491..81961ee 100644 --- a/motioneye/uploadservices.py +++ b/motioneye/uploadservices.py @@ -15,10 +15,12 @@ # You should have received a copy of the GNU General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. +import ftplib import json import logging import mimetypes import os.path +import StringIO import time import urllib import urllib2 @@ -603,6 +605,106 @@ class Dropbox(UploadService): } +class FTP(UploadService): + NAME = 'ftp' + CONN_LIFE_TIME = 60 # don't keep an FTP connection for more than 1 minute + + def __init__(self, camera_id, server=None, port=None, username=None, password=None, location=None, **kwargs): + self._server = server + self._port = port + self._username = username or 'anonymous' + self._password = password or '' + self._location = location + + self._conn = None + self._conn_time = 0 + + UploadService.__init__(self, camera_id) + + def test_access(self): + try: + conn = self._get_conn() + + path = self._make_dirs(self._location, conn=conn) + conn.cwd(path) + + d = '%s' % int(time.time()) + self.debug('creating test directory %s/%s' % (path, d)) + conn.mkd(d) + conn.rmd(d) + + return True + + except Exception as e: + self.error(str(e), exc_info=True) + + return str(e) + + def upload_data(self, filename, mime_type, data): + path = os.path.dirname(filename) + filename = os.path.basename(filename) + + conn = self._get_conn() + path = self._make_dirs(self._location + '/' + path, conn=conn) + conn.cwd(path) + + self.debug('uploading %s of %s bytes' % (filename, len(data))) + conn.storbinary('STOR %s' % filename, StringIO.StringIO(data)) + + self.debug('upload done') + + def dump(self): + return { + 'server': self._server, + 'port': self._port, + 'username': self._username, + 'password': self._password, + 'location': self._location + } + + def load(self, data): + if data.get('server') is not None: + self._server = data['server'] + if data.get('port') is not None: + self._port = int(data['port']) + if data.get('username') is not None: + self._username = data['username'] + if data.get('password') is not None: + self._password = data['password'] + if data.get('location'): + self._location = data['location'] + + def _get_conn(self): + now = time.time() + if self._conn is None or now - self._conn_time > self.CONN_LIFE_TIME: + self.debug('creating connection to %s@%s:%s' % (self._username, self._server, self._port)) + self._conn = ftplib.FTP() + self._conn.set_pasv(True) + self._conn.connect(self._server, port=self._port) + self._conn.login(self._username, self._password) + self._conn_time = now + + return self._conn + + def _make_dirs(self, path, conn=None): + conn = conn or self._get_conn() + + path = path.split('/') + path = [p for p in path if p] + + self.debug('ensuring path /%s' % '/'.join(path)) + + conn.cwd('/') + for p in path: + l = conn.nlst() + if p not in l: + conn.mkd(p) + + conn.cwd(p) + + return '/' + '/'.join(path) + + def get_authorize_url(service_name): cls = UploadService.get_service_classes().get(service_name)