NukeFS Ultimate (NFSU): twin-algorithm shortener-based file cloud storage for Python 2.6+


SUBMITTED BY: Guest

DATE: Oct. 30, 2012, 1 p.m.

FORMAT: Python

SIZE: 4.9 kB

HITS: 2230

  1. #!/usr/bin/env python
  2. '''
  3. NukeFS Ultimate (NFSU): twin-algorithm shortener-based file cloud storage for Python 2.6+
  4. Full library and command-line implementation
  5. by Multiversum
  6. Usage as stand-alone application: see nukefs.py -h
  7. Usage as library:
  8. import nukefs
  9. //for master-chunk algorithm:
  10. key_of_file = nukefs.upload("file.zip")
  11. download(key_of_file, "downoaded.zip")
  12. //for streaming algorithm:
  13. key_of_file = nukefs.upload("file.zip", True)
  14. download(key_of_file, "downoaded.zip", True)
  15. Note: it gets damn slow and somewhat unstable on large files so plz don't upload >1M files
  16. '''
  17. from requests import get
  18. from json import dumps, loads
  19. from urllib import quote_plus, unquote_plus
  20. CHUNKLEN=22000 #current TinyURL effective chunk length limitation
  21. def chunk_upload(localpath):
  22. filekeys = []
  23. baseurl = 'http://tinyurl.com/api-create.php?url='
  24. with open(localpath, 'rb') as fileobj:
  25. while 1:
  26. data = fileobj.read(CHUNKLEN)
  27. if not data: break
  28. encoded = quote_plus(''.join(data.encode('base64').splitlines()))
  29. key = get(baseurl+encoded).text[19:]
  30. filekeys.append(key)
  31. fileobj.close()
  32. return get(baseurl+quote_plus(dumps(filekeys))).text[19:]
  33. def chunk_download(filekey, localpath):
  34. filekeys = loads(unquote_plus(get('http://tinyurl.com/'+filekey, allow_redirects=False).headers['location']))
  35. with open(localpath, 'wb') as fileobj:
  36. for key in filekeys:
  37. data = get('http://tinyurl.com/'+key, allow_redirects=False).headers['location']
  38. if not data: break
  39. fileobj.write(unquote_plus(data).decode('base64'))
  40. fileobj.close()
  41. def stream_upload(localpath):
  42. chunks = []
  43. with open(localpath, 'rb') as fileobj:
  44. while 1:
  45. data = fileobj.read(CHUNKLEN)
  46. if not data: break
  47. chunks.append(''.join(data.encode('base64').splitlines()))
  48. fileobj.close()
  49. baseurl = 'http://tinyurl.com/api-create.php?url='
  50. key = None
  51. for i in xrange(len(chunks),0,-1):
  52. chunkobj = {'data' : chunks[i-1], 'next' : key}
  53. encoded = quote_plus(dumps(chunkobj))
  54. key = get(baseurl+encoded).text[19:]
  55. return key
  56. def stream_download(key, localpath):
  57. with open(localpath, 'wb') as fileobj:
  58. while 1:
  59. data = get('http://tinyurl.com/'+key, allow_redirects=False).headers['location']
  60. if not data: break
  61. chunkobj = loads(unquote_plus(data))
  62. if not chunkobj['data']: break
  63. fileobj.write(chunkobj['data'].decode('base64'))
  64. if not chunkobj['next']: break
  65. key = chunkobj['next']
  66. fileobj.close()
  67. #universal functions to be called outside
  68. #algo: False - master-chunk algorithm (default), True - streaming algorithm
  69. def upload(localpath, algo=None):
  70. '''
  71. Upload a file from localpath to cloud and get its access key
  72. algo: False or None - master-chunk algorithm (default), True - streaming algorithm
  73. '''
  74. if algo:
  75. return stream_upload(localpath)
  76. else:
  77. return chunk_upload(localpath)
  78. def download(filekey, localpath, algo=None):
  79. '''
  80. Download a file to localpath by its access key
  81. algo: False or None - master-chunk algorithm (default), True - streaming algorithm
  82. '''
  83. if algo:
  84. stream_download(filekey, localpath)
  85. else:
  86. chunk_download(filekey, localpath)
  87. #stand-alone app code
  88. if __name__ == '__main__':
  89. from optparse import OptionParser
  90. parser = OptionParser()
  91. parser.add_option("-u", dest="upfilename",
  92. help="upload FILE to cloud", metavar="FILE")
  93. parser.add_option("-d", dest="downfilename",
  94. help="download FILE from cloud", metavar="FILE")
  95. parser.add_option("-k", dest="accesskey",
  96. help="Access key to download a file")
  97. parser.add_option("-s", "--stream", action="store_true", dest="algo",
  98. help="Use streaming algorithm instead of chunked")
  99. (options, args) = parser.parse_args()
  100. if options.upfilename and options.downfilename:
  101. parser.error("You can either download or upload at the same time")
  102. if options.downfilename and not options.accesskey:
  103. parser.error("You must specify the access key (with -k option) to download a file")
  104. if options.upfilename:
  105. print 'Uploading...'
  106. accesskey = upload(options.upfilename, options.algo)
  107. print 'Done. File access key is', accesskey
  108. elif options.downfilename:
  109. print 'Downloading...'
  110. download(options.accesskey, options.downfilename, options.algo)
  111. print 'Done.'
  112. else:
  113. print "Please specify either the file to upload or the file to download. See nukefs.py -h for help."

comments powered by Disqus