daily pastebin goal
11%
SHARE
TWEET

AWS S3 Python Boto File Utils Example

ericsaupe Dec 3rd, 2013 207 Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. class FileUtils:
  2.         def __init__(self, companyID):
  3.                 self.companyID = companyID
  4.                 self.rootFolder = '%sClient Number/%s/' % (settings.FILE_ROOT, companyID)
  5.                 self.s3Connection = boto.connect_s3() #This opens the connection to our s3 instance
  6.                 self.s3Bucket = self.s3Connection.get_bucket(settings.S3_BUCKET) #This gets the s3 bucket
  7.  
  8.         def save_file(self, path=None, data=None):
  9.                 """
  10.                 This method saves a file to the given path.  If none is given for either the path or the data it will return false.
  11.                 Parameters:
  12.                         path - The path to save the file in
  13.                         data - The file to be saved
  14.  
  15.                 Returns:
  16.                         True if the file was saved successfully otherwise an error will be thrown.
  17.                 """
  18.                 if data is None or path is None:
  19.                         return False
  20.                 if not "Files/Client Number/" in path:
  21.                         path = "%s%s" % (self.rootFolder, path)
  22.                 k = self.s3Bucket.new_key(path)
  23.  
  24.                 if (path[path.rfind('.'):] == '.pdf'):
  25.                         k.set_contents_from_string(data, headers={'Content-Type': 'application/pdf'})
  26.                 else:
  27.                         k.set_contents_from_string(data)
  28.  
  29.                 return self.get_contents(None, path[:path.rfind('/') + 1])
  30.  
  31.         def create_folder(self, request, path=""):
  32.                 """
  33.                 This method creates a folder in the given path.  If one is not given it is created in the root.
  34.  
  35.                 Parameters:
  36.                         path - where the folder will be created.  Empty string will create the folder in root.
  37.  
  38.                 Returns:
  39.                         True if the folder was created succesfully.
  40.                 """
  41.                 if request.POST.get('name') is None:
  42.                         return False
  43.                 newFolderName = request.POST.get('name', '')
  44.                 if path == '':
  45.                         path = self.rootFolder
  46.                 newFolder = '%s%s/' % (path, newFolderName)
  47.                 try:
  48.                         k = self.s3Bucket.new_key(newFolder)
  49.                         k.set_contents_from_string("")
  50.                 except:
  51.                         return HttpResponse("Folder Name in Use", mimetype="text/plain")
  52.  
  53.                 return self.get_contents(None, path)
  54.  
  55.         def delete(self, request, path=None):
  56.                 """
  57.                 This method deletes the element given in path.
  58.  
  59.                 Parameters:
  60.                         path - path to the element to be deleted
  61.  
  62.                 Returns:
  63.                         Contents of the parent folder
  64.                 """
  65.                 if path is None:
  66.                         return False
  67.  
  68.                 #get current shares that are contained in this share and unshare them
  69.                 PendingFileSharesPermissions.objects.filter(path__path__contains=path).delete()
  70.                 PendingFileShares.objects.filter(path__contains=path).delete()
  71.                 #get current shares that are contained in this share and unshare them
  72.                 FileSharesPermissions.objects.filter(path__path__contains=path).delete()
  73.                 FileShares.objects.filter(path__contains=path).delete()
  74.  
  75.                 if FileUtils.is_file(path):
  76.                         parent = path[:path.rfind('/') + 1]
  77.                 elif FileUtils.is_folder(path):
  78.                         keyList = self.s3Bucket.list(prefix=path)
  79.                         for key in keyList:
  80.                                 self.s3Bucket.delete_key(key.name)
  81.                         parent = path[:path.rfind('/')]
  82.                         parent = parent[:parent.rfind('/') + 1]
  83.                 k = self.s3Bucket.get_key(path)
  84.                 if (k is not None):
  85.                         self.s3Bucket.delete_key(k)
  86.                 return self.get_contents(None, parent)
  87.  
  88.         def get_file(self, path=None, isFile=True):
  89.                 """
  90.                 This method fetches the file at path and returns it.
  91.  
  92.                 Parameters:
  93.                         path - The path of the requested file
  94.  
  95.                 Returns:
  96.                         The file at the requested path
  97.                 """
  98.                 if path is None:
  99.                         return None
  100.                 if isFile:
  101.                         allowedAccess = False
  102.                         if path[:self.rootFolder.__len__()] == self.rootFolder:
  103.                                 allowedAccess = True
  104.                         else:
  105.                                 shares = FileSharesPermissions.objects.filter(company=self.companyID)
  106.                                 for share in shares:
  107.                                         if share.path.path in path:
  108.                                                 allowedAccess = True
  109.                                                 break
  110.                         if not allowedAccess:
  111.                                 return False
  112.                 k = self.s3Bucket.get_key(path)
  113.                 url = ''
  114.                 if k:
  115.                         url = k.generate_url(120)
  116.                 return url
  117.  
  118.         def get_raw_file(self, path=None, isFile=True):
  119.                 """
  120.                 This method fetches the file at path and returns it.
  121.  
  122.                 Parameters:
  123.                         path - The path of the requested file
  124.  
  125.                 Returns:
  126.                         The file at the requested path
  127.                 """
  128.                 if path is None:
  129.                         return None
  130.                 if isFile:
  131.                         allowedAccess = False
  132.                         if path[:self.rootFolder.__len__()] == self.rootFolder:
  133.                                 allowedAccess = True
  134.                         else:
  135.                                 shares = FileSharesPermissions.objects.filter(company=self.companyID)
  136.                                 for share in shares:
  137.                                         if share.path.path in path:
  138.                                                 allowedAccess = True
  139.                                                 break
  140.                         if not allowedAccess:
  141.                                 return False
  142.                 k = self.s3Bucket.get_key(path)
  143.                 fileName = k.get_contents_as_string()
  144.                 return fileName
  145.  
  146.         def move(self, request, path=None):
  147.                 """
  148.                 This method renames the file by copying the key to a new key with the new name and deleting the old one.
  149.                 Functions like the Unix move command.
  150.  
  151.                 Parameters:
  152.                         request - contains POST data with the new name
  153.                         path - The relative path of the item to be moved
  154.  
  155.                 Returns:
  156.                         Contents of the parent folder to be used in refreshing the list
  157.                 """
  158.                 if path is None:
  159.                         return None
  160.                 #Get the path
  161.                 shared = True
  162.                 if path[:self.rootFolder.__len__()] == self.rootFolder:
  163.                         shared = False
  164.                 #Move the file or folder
  165.                 if FileUtils.is_file(path):
  166.                         #Move places the file into the new folder
  167.                         if request.POST.get('move') == 'true':
  168.                                 if request.POST.get('name') != "fileslist":
  169.                                         newFolder = "%s%s" % (self.rootFolder, request.POST.get('name'))
  170.                                 else:
  171.                                         newFolder = "%s" % (self.rootFolder)
  172.                                 if not self.s3Bucket.get_key(newFolder):
  173.                                         k = self.s3Bucket.new_key(newFolder)
  174.                                         k.set_contents_from_string("")
  175.                                 newName = "%s%s" % (newFolder, path[path.rfind('/')+1:])
  176.                         #Non-Move calls rename the file in its current folder
  177.                         else:
  178.                                 if not self.s3Bucket.get_key(path[:path.rfind('/')+1]):
  179.                                         k = self.s3Bucket.new_key(path[:path.rfind('/')+1])
  180.                                         k.set_contents_from_string("")
  181.                                 newName = "%s%s%s" % (path[:path.rfind('/')+1], request.POST.get('name'), path[path.rfind('.'):])
  182.                         self.s3Bucket.copy_key(newName, settings.S3_BUCKET, path)
  183.                         #If the file is not in a shared directory we can remove it and update file sharing if it exists
  184.                         if not shared:
  185.                                 shared = FileShares.objects.filter(path=path)
  186.                                 for share in shared:
  187.                                         share.path = newName
  188.                                         share.save()
  189.                                 self.s3Bucket.delete_key(path)
  190.                 #Folder names need to be pulled out of their current path
  191.                 elif FileUtils.is_folder(path):
  192.                         #Move holds the folder name the same but appends it to the desitination folder
  193.                         if request.POST.get('move') == 'true':
  194.                                 newName = path[:path.rfind('/')]
  195.                                 newName = newName[newName.rfind('/')+1:]
  196.                                 newName = "%s%s%s/" % (self.rootFolder, request.POST.get('name'), newName)
  197.                         #Rename changes the folder name
  198.                         else:
  199.                                 newName = path[:path.rfind('/')]
  200.                                 newName = newName[:newName.rfind('/')+1]
  201.                                 newName = "%s%s/" % (newName, request.POST.get('name'))
  202.                         #Update any filesharing information
  203.                         shared = FileShares.objects.filter(path=path)
  204.                         for share in shared:
  205.                                 share.path = newName
  206.                                 share.save()
  207.                         #Alter the contents of the folder
  208.                         FileUtils._move_folder(self, path, newName)
  209.                 #Get the parent to return it's contents
  210.                 if FileUtils.is_file(path):
  211.                         parent = path[:path.rfind('/') + 1]
  212.                 elif FileUtils.is_folder(path):
  213.                         parent = path[:path.rfind('/')]
  214.                         parent = parent[:parent.rfind('/') + 1]
  215.                 return self.get_contents(None, parent)
  216.  
  217.         def move_file(self, oldPath, newPath):
  218.                 self.s3Bucket.copy_key(newPath, settings.S3_BUCKET, oldPath)
  219.                 self.s3Bucket.delete_key(oldPath)
  220.                 return True
  221.  
  222.         def _move_folder(self, path, name):
  223.                 """
  224.                 Recursive helper method to move folders and their containing files
  225.  
  226.                 Parameters:
  227.                         self
  228.                         path - key name for the folder to be changed
  229.                         name - new key name to replace old path
  230.                 """
  231.                 for key in self.s3Bucket.list(prefix=path, delimiter="/"):
  232.                         if FileUtils.is_file(key.name):
  233.                                 newName = "%s%s" %(name, key.name[key.name.rfind('/')+1:])
  234.                                 self.s3Bucket.copy_key(newName, settings.S3_BUCKET, key.name)
  235.                                 self.s3Bucket.delete_key(key.name)
  236.                         elif FileUtils.is_folder(key.name):
  237.                                 newFolder = key.name[:key.name.rfind('/')]
  238.                                 newFolder = "%s%s/" % (name, newFolder[newFolder.rfind('/')+1:])
  239.                                 if self.s3Bucket.get_key(key.name):
  240.                                         self.s3Bucket.copy_key(newFolder, settings.S3_BUCKET, key.name)
  241.                                         self.s3Bucket.delete_key(key.name)
  242.                                 else:
  243.                                         k = self.s3Bucket.new_key(newFolder)
  244.                                         k.set_contents_from_string("")
  245.                                 if key.name != path:
  246.                                         FileUtils._move_folder(self, key.name, newFolder)
  247.  
  248.         @staticmethod  
  249.         def is_file(path):
  250.                 """
  251.                 This method may need to become more robust in the future, but it's purpose is to detect within amazon s3 whether a given path is a file.
  252.  
  253.                 Parameters:
  254.                         path - The path of the file
  255.  
  256.                 Returns:
  257.                         true if the path is a file, otherwise false
  258.                 """
  259.                 foldername, filename = os.path.split(path)
  260.                 return filename != ''
  261.  
  262.         @staticmethod
  263.         def is_folder(path):
  264.                 """
  265.                 This method may need to become more robust in the future, but it's purpose is to detect within amazon s3 whether a given path is a folder.
  266.  
  267.                 Parameters:
  268.                         path - The path of the folder
  269.  
  270.                 Returns:
  271.                         true if the path is a folder, otherwise false
  272.                 """
  273.                 foldername, filename = os.path.split(path)
  274.                 return filename == ''
  275.  
  276.         def get_contents(self, subFolder=None, path=None):     
  277.                 """
  278.                 This method gets the file list for all files and what folder they are contained in for a given path.  It drives the recursive method that gets the contents for all folders and their subfolders.
  279.  
  280.                 Parameters:
  281.                         subFolder - The subfolder of the root directory to begin at
  282.                         path - Explicit path to get contents
  283.  
  284.                 Returns:
  285.                         A dictionary of files and folders with their contents.
  286.                 """
  287.                 contents = self._get_contents(subFolder, path)
  288.                 if path is None or path == self.rootFolder:
  289.                         #now get the shared stuff
  290.                         sharedContents = {'folders':[], 'files':[]}
  291.                         shared = FileSharesPermissions.objects.filter(company__in=[self.companyID, 0])
  292.                         for share in shared:
  293.                                 path = share.path.path
  294.                                 if path[:self.rootFolder.__len__()] == self.rootFolder:
  295.                                         continue
  296.                                 shareContents = {'folders':[], 'files':[]}
  297.                                 for key in self.s3Bucket.list(prefix=path, delimiter="/"):
  298.                                         if key.name.startswith("."):
  299.                                                 continue
  300.                                         if FileUtils.is_folder(key.name):
  301.                                                 if key.name == path:
  302.                                                         continue
  303.                                                 shareContents['folders'].append({"foldername":key.name.replace(path, ""), "meta":{"size":'--', 'moddate':'--', 'fullpath':key.name}, 'contents':{'folders':[], 'files':[]}})
  304.  
  305.                                         if FileUtils.is_file(key.name):
  306.                                                 s = key.size
  307.                                                 d = datetime.datetime.strptime(key.last_modified[:19], "%Y-%m-%dT%H:%M:%S")
  308.                                                 if key.name == path:
  309.                                                         folderName, keyName = os.path.split(path)
  310.                                                 else:
  311.                                                         keyName = key.name.replace(path, "")
  312.                                                 shareContents['files'].append({"filename":keyName, "meta":{"size":FileUtils.convert_bytes(s), "moddate":d.strftime("%m/%d/%y %H:%M:%S"), 'fullpath':key.name}})
  313.                                 if FileUtils.is_folder(path):
  314.                                         sharedContents['folders'].append({'foldername':("%s/" % os.path.basename(os.path.normpath(path))), 'meta':{'size':'--', 'moddate':'--', 'fullpath':path}, 'contents':shareContents})
  315.                                 else:
  316.                                         sharedContents['files'].extend(shareContents['files'])
  317.  
  318.                         contents['folders'].append({"foldername":"SHARED/", "meta":{"size":"--", 'moddate':'--'}, 'contents':sharedContents})
  319.  
  320.                 return contents
  321.  
  322.         def _get_contents(self, subFolder=None, path=None):
  323.                 """
  324.                 This method gets the file list for all files and what folder they are contained in for a given path.  It recursively gets the contents for all folders and their subfolders.
  325.  
  326.                 Parameters:
  327.                         subFolder - The subfolder of the root directory to begin at
  328.                         path - Explicit path to get contents
  329.  
  330.                 Returns:
  331.                         A dictionary of files and folders with their contents.
  332.                 """
  333.                 if subFolder is None and path is None:
  334.                         path = self.rootFolder
  335.                 elif subFolder is not None and path is None:
  336.                         path = "%s%s/" % (self.rootFolder, subFolder)
  337.                 elif subFolder is not None and path is not None:
  338.                         path = "%s%s/" % (path, subFolder)
  339.  
  340.                 contents = {'folders':[], 'files':[]}
  341.                 for key in self.s3Bucket.list(prefix=path, delimiter="/"):
  342.                         if key.name.startswith("."):
  343.                                 continue
  344.                         if FileUtils.is_folder(key.name):
  345.                                 #Specification files will be handled by the user through the Specification Files page
  346.                                 if key.name == path or key.name == self.rootFolder + 'SPECIFICATION FILES/':
  347.                                         continue
  348.                                 contents['folders'].append({"foldername":key.name.replace(path, ""), "meta":{"size":'--', 'moddate':'--', 'fullpath':key.name}, 'contents':{'folders':[], 'files':[]}})
  349.  
  350.                         if FileUtils.is_file(key.name):
  351.                                 s = key.size
  352.                                 d = datetime.datetime.strptime(key.last_modified[:19], "%Y-%m-%dT%H:%M:%S")
  353.                                 contents['files'].append({"filename":key.name.replace(path, ""), "meta":{"size":FileUtils.convert_bytes(s), "moddate":d.strftime("%m/%d/%y %H:%M:%S"), 'fullpath':key.name}})
  354.  
  355.                 return contents
  356.  
  357.                 @staticmethod  
  358.                 def convert_bytes(bytes):              
  359.                 """            
  360.                This is a static helper method to convert bytes into a readable format
  361.                 Parameters:     bytes - Bytes to be formated
  362.                 Returns:        A string representation of the bytes in a more readable format         
  363.                """
  364.                 bytes = float(bytes)
  365.                 if bytes >= 1099511627776:
  366.                         terabytes = bytes / 1099511627776
  367.                         size = '%.2fTB' % terabytes
  368.                 elif bytes >= 1073741824:
  369.                         gigabytes = bytes / 1073741824
  370.                         size = '%.2fGB' % gigabytes
  371.                 elif bytes >= 1048576:
  372.                         megabytes = bytes / 1048576
  373.                         size = '%.2fMB' % megabytes
  374.                 elif bytes >= 1024:
  375.                         kilobytes = bytes / 1024
  376.                         size = '%.2fKB' % kilobytes
  377.                 else:
  378.                         size = '%.2fB' % bytes
  379.                 return size
RAW Paste Data
We use cookies for various purposes including analytics. By continuing to use Pastebin, you agree to our use of cookies as described in the Cookies Policy. OK, I Understand
 
Top