forked from seba/servefile
Moved FileHandler functions to FileBaseHandler
FileHandler hat core functionality used/needed by other Handlers.
This commit is contained in:
parent
790607eabc
commit
b11710da39
134
servefile
134
servefile
|
@ -101,9 +101,104 @@ class FileBaseHandler(BaseHTTPServer.BaseHTTPRequestHandler):
|
||||||
return (True, None)
|
return (True, None)
|
||||||
return (True, fromto)
|
return (True, fromto)
|
||||||
# broken request or no range header
|
# broken request or no range header
|
||||||
pass
|
|
||||||
return (False, None)
|
return (False, None)
|
||||||
|
|
||||||
|
def sendFile(self, filePath, fileLength=None, lastModified=None):
|
||||||
|
""" Send file with continuation support.
|
||||||
|
|
||||||
|
filePath: path to file to be sent
|
||||||
|
fileLength: length of file (if None is given this will be found out)
|
||||||
|
lastModified: time the file was last modified, None for "now"
|
||||||
|
"""
|
||||||
|
if not fileLength:
|
||||||
|
fileLength = os.stat(filePath)[ST_SIZE]
|
||||||
|
|
||||||
|
(responseCode, myfile) = self.getFileHandle(filePath)
|
||||||
|
if not myfile:
|
||||||
|
self.send_response(responseCode)
|
||||||
|
self.end_headers()
|
||||||
|
return
|
||||||
|
|
||||||
|
(continueDownload, fromto) = self.handleRangeRequest(fileLength)
|
||||||
|
if continueDownload:
|
||||||
|
if not fromto:
|
||||||
|
# we are done
|
||||||
|
return True
|
||||||
|
|
||||||
|
# now we can wind the file *brrrrrr*
|
||||||
|
myfile.seek(fromto[0])
|
||||||
|
|
||||||
|
if fromto != None:
|
||||||
|
self.send_response(216)
|
||||||
|
self.send_header('Content-Range', 'bytes %s-%s/%s' % (fromto[0], fromto[1], fileLength))
|
||||||
|
fileLength = fromto[1] - fromto[0] + 1
|
||||||
|
else:
|
||||||
|
self.send_response(200)
|
||||||
|
|
||||||
|
fileName = self.fileName
|
||||||
|
if not fileName:
|
||||||
|
fileName = os.path.basename(filePath)
|
||||||
|
self.sendContentHeaders(fileName, fileLength, lastModified)
|
||||||
|
self.end_headers()
|
||||||
|
block = self.getChunk(myfile, fromto)
|
||||||
|
while block:
|
||||||
|
try:
|
||||||
|
self.wfile.write(block)
|
||||||
|
except socket.error, e:
|
||||||
|
print "%s ABORTED transmission (Reason %s: %s)" % (self.client_address[0], e[0], e[1])
|
||||||
|
return False
|
||||||
|
block = self.getChunk(myfile, fromto)
|
||||||
|
myfile.close()
|
||||||
|
print "%s finished downloading %s" % (self.client_address[0], filePath)
|
||||||
|
return True
|
||||||
|
|
||||||
|
def getChunk(self, myfile, fromto):
|
||||||
|
if fromto and myfile.tell()+self.blockSize >= fromto[1]:
|
||||||
|
readsize = fromto[1]-myfile.tell()+1
|
||||||
|
else:
|
||||||
|
readsize = self.blockSize
|
||||||
|
return myfile.read(readsize)
|
||||||
|
|
||||||
|
def getFileHandle(self, path):
|
||||||
|
""" Get handle to a file.
|
||||||
|
|
||||||
|
Return a tuple of HTTP response code and file handle.
|
||||||
|
If the handle couldn't be acquired it is set to None
|
||||||
|
and an appropriate HTTP error code is returned.
|
||||||
|
"""
|
||||||
|
myfile = None
|
||||||
|
responseCode = 200
|
||||||
|
try:
|
||||||
|
myfile = open(path, 'rb')
|
||||||
|
except IOError, e:
|
||||||
|
responseCode = self.getResponseForErrno(e.errno)
|
||||||
|
return (responseCode, myfile)
|
||||||
|
|
||||||
|
def getFileLength(self, path):
|
||||||
|
""" Get length of a file.
|
||||||
|
|
||||||
|
Return a tuple of HTTP response code and file length.
|
||||||
|
If filelength couldn't be determined, it is set to -1
|
||||||
|
and an appropriate HTTP error code is returned.
|
||||||
|
"""
|
||||||
|
fileSize = -1
|
||||||
|
responseCode = 200
|
||||||
|
try:
|
||||||
|
fileSize = os.stat(path)[ST_SIZE]
|
||||||
|
except IOError, e:
|
||||||
|
responseCode = self.getResponseForErrno(e.errno)
|
||||||
|
return (responseCode, fileSize)
|
||||||
|
|
||||||
|
def getResponseForErrno(self, errno):
|
||||||
|
""" Return HTTP response code for an IOError errno """
|
||||||
|
if errno == 2:
|
||||||
|
return 404
|
||||||
|
elif errno == 13:
|
||||||
|
return 403
|
||||||
|
else:
|
||||||
|
return 500
|
||||||
|
|
||||||
|
|
||||||
class FileHandler(FileBaseHandler):
|
class FileHandler(FileBaseHandler):
|
||||||
filePath = "/dev/null"
|
filePath = "/dev/null"
|
||||||
fileLength = 0
|
fileLength = 0
|
||||||
|
@ -119,43 +214,8 @@ class FileHandler(FileBaseHandler):
|
||||||
def do_GET(self):
|
def do_GET(self):
|
||||||
if self.checkAndDoRedirect():
|
if self.checkAndDoRedirect():
|
||||||
return
|
return
|
||||||
myfile = open(self.filePath, 'rb')
|
self.sendFile(self.filePath, self.fileLength, self.startTime)
|
||||||
|
|
||||||
(continueDownload, fromto) = self.handleRangeRequest(self.fileLength)
|
|
||||||
if continueDownload:
|
|
||||||
if not fromto:
|
|
||||||
# we are done
|
|
||||||
return
|
|
||||||
|
|
||||||
# now we can wind the file *brrrrrr*
|
|
||||||
myfile.seek(fromto[0])
|
|
||||||
|
|
||||||
fileLength = self.fileLength
|
|
||||||
if fromto != None:
|
|
||||||
self.send_response(216)
|
|
||||||
self.send_header('Content-Range', 'bytes %s-%s/%s' % (fromto[0], fromto[1], self.fileLength))
|
|
||||||
fileLength = fromto[1] - fromto[0] + 1
|
|
||||||
else:
|
|
||||||
self.send_response(200)
|
|
||||||
self.sendContentHeaders(self.fileName, fileLength, self.startTime)
|
|
||||||
self.end_headers()
|
|
||||||
block = self.getChunk(myfile, fromto)
|
|
||||||
while block:
|
|
||||||
try:
|
|
||||||
self.wfile.write(block)
|
|
||||||
except socket.error, e:
|
|
||||||
print "%s ABORTED transmission (Reason %s: %s)" % (self.client_address[0], e[0], e[1])
|
|
||||||
return
|
|
||||||
block = self.getChunk(myfile, fromto)
|
|
||||||
myfile.close()
|
|
||||||
print "%s finished downloading" % (self.client_address[0])
|
|
||||||
|
|
||||||
def getChunk(self, myfile, fromto):
|
|
||||||
if fromto and myfile.tell()+self.blockSize >= fromto[1]:
|
|
||||||
readsize = fromto[1]-myfile.tell()+1
|
|
||||||
else:
|
|
||||||
readsize = self.blockSize
|
|
||||||
return myfile.read(readsize)
|
|
||||||
|
|
||||||
class TarFileHandler(FileBaseHandler):
|
class TarFileHandler(FileBaseHandler):
|
||||||
target = None
|
target = None
|
||||||
|
|
Loading…
Reference in New Issue