def nodes_download(request): """ Download multiple nodes (documents and folders) packed as tar.gz archive. """ node_ids = request.GET.getlist('node_ids[]') nodes = BaseTreeNode.objects.filter(id__in=node_ids) nodes_perms = request.user.get_perms_dict(nodes, Access.ALL_PERMS) for node in nodes: if not nodes_perms[node.id].get(Access.PERM_READ, False): msg = _("%s does not have permission to read %s") % ( request.user.username, node.title) return msg, HttpResponseForbidden.status_code with NamedTemporaryFile(prefix="download_") as fileobj: build_tar_archive(fileobj=fileobj, node_ids=node_ids) # reset fileobj to initial position fileobj.seek(0) data = fileobj.read() resp = HttpResponse(data, content_type="application/x-tar") disposition = "attachment; filename=download.tar" resp['Content-Disposition'] = disposition return resp
def node_download(request, id): """ Any user with read permission on the node must be able to download it. Node is either documennt or a folder. """ version = request.GET.get('version', None) try: node = BaseTreeNode.objects.get(id=id) except BaseTreeNode.DoesNotExist: raise Http404("Node does not exists") if request.user.has_perm(Access.PERM_READ, node): if node.is_document(): try: file_handle = open(default_storage.abspath( node.path().url(version=version) ), "rb") except OSError: logger.error( "Cannot open local version of %s" % node.path.url() ) return redirect('admin:browse') resp = HttpResponse( file_handle.read(), content_type="application/pdf" ) disposition = "attachment; filename=%s" % node.title resp['Content-Disposition'] = disposition file_handle.close() return resp else: # node is a folder with NamedTemporaryFile(prefix="download_") as fileobj: # collected into an archive all direct children of # selected folder node_ids = [_node.id for _node in node.get_children()] build_tar_archive( fileobj=fileobj, node_ids=node_ids ) # reset fileobj to initial position fileobj.seek(0) data = fileobj.read() resp = HttpResponse( data, content_type="application/x-tar" ) disposition = f"attachment; filename={node.title}.tar" resp['Content-Disposition'] = disposition return resp return HttpResponseForbidden()
def test_basic_two_folders(self): """ Creates following hierarchy: + Folder_1 + berlin_f_1.pdf + Folder_2 + berlin_f_2.pdf + berlin_root_1.pdf + berlin_root_2.pdf """ f1 = Folder.objects.create(title='Folder_1', parent=None, user=self.testcase_user) f2 = Folder.objects.create(title='Folder_2', parent=None, user=self.testcase_user) document_path = os.path.join(BASE_DIR, "data", "berlin.pdf") doc_in_root_1 = Document.objects.create_document( user=self.testcase_user, title='berlin_root_1.pdf', size=os.path.getsize(document_path), lang='deu', file_name='berlin_root_1.pdf', page_count=3) default_storage.copy_doc( src=document_path, dst=doc_in_root_1.path.url(), ) doc_in_root_2 = Document.objects.create_document( user=self.testcase_user, title='berlin_root_2.pdf', size=os.path.getsize(document_path), lang='deu', file_name='berlin_root_2.pdf', page_count=3) default_storage.copy_doc( src=document_path, dst=doc_in_root_2.path.url(), ) doc_in_f_1 = Document.objects.create_document( user=self.testcase_user, title='berlin_f_1.pdf', size=os.path.getsize(document_path), lang='deu', parent_id=f1.id, file_name='berlin_f_1.pdf', page_count=3) default_storage.copy_doc( src=document_path, dst=doc_in_f_1.path.url(), ) doc_in_f_2 = Document.objects.create_document( user=self.testcase_user, title='berlin_f_2.pdf', size=os.path.getsize(document_path), lang='deu', parent_id=f2.id, file_name='berlin_f_2.pdf', page_count=3) default_storage.copy_doc( src=document_path, dst=doc_in_f_2.path.url(), ) """ User selected two documents in the root dir berlin_root_1.pdf, and berlin_root_1.pdf plus Folder_1 and Folder_2. Selection is marked with square brackets [...] + [Folder_1] + berlin_f_1.pdf + [Folder_2] + berlin_f_2.pdf + [berlin_root_1.pdf] + [berlin_root_2.pdf] """ selected_ids = [doc_in_root_1.id, doc_in_root_2.id, f1.id, f2.id] with io.BytesIO() as memoryfile: build_tar_archive( # <-- THIS IS WHAT WE ARE TESTING fileobj=memoryfile, node_ids=selected_ids) memoryfile.seek(0) archive_file = tarfile.open(fileobj=memoryfile, mode='r') berlin_root_1_handle = archive_file.extractfile( 'berlin_root_1.pdf') data = berlin_root_1_handle.read() self.assertTrue(len(data) > 0) berlin_f_1_handle = archive_file.extractfile( 'Folder_1/berlin_f_1.pdf') data = berlin_f_1_handle.read() self.assertTrue(len(data) > 0) berlin_f_2_handle = archive_file.extractfile( 'Folder_2/berlin_f_2.pdf') data = berlin_f_2_handle.read() self.assertTrue(len(data) > 0) with self.assertRaises(KeyError): # there is no file Accounting/Expenses/Paris.pdf # in archive, thus, KeyError exception is expected archive_file.extractfile('Accounting/Expenses/Paris.pdf')