'Resume upload of a file already part-uploaded to Glacier.
The resumption of an upload where the part-uploaded section is empty
is a valid degenerate case that this function can handle.
One and only one of filename or file_obj must be specified.
:type upload_id: str
:param upload_id: existing Glacier upload id of upload being resumed.
:type filename: str
:param filename: file to open for resume
:type fobj: file
:param fobj: file-like object containing local data to resume. This
must read from the start of the entire upload, not just from the
point being resumed. Use fobj.seek(0) to achieve this if necessary.
:rtype: str
:return: The archive id of the newly created archive'

def resume_archive_from_file(self, upload_id, filename=None, file_obj=None):

    part_list_response = self.list_all_parts(upload_id)
    part_size = part_list_response['PartSizeInBytes']
    part_hash_map = {}
    for part_desc in part_list_response['Parts']:
        part_index = self._range_string_to_part_index(part_desc['RangeInBytes'], part_size)
        part_tree_hash = codecs.decode(part_desc['SHA256TreeHash'], 'hex_codec')
        part_hash_map[part_index] = part_tree_hash
    if (not file_obj):
        file_obj = open(filename, 'rb')
    return resume_file_upload(self, upload_id, part_size, file_obj, part_hash_map)
