def get_path_response(self, path, request, force_download=False, paginator=None): self.validate_path(path) try: if not path: raise OSError(errno.EISDIR, os.strerror(errno.EISDIR), path) if os.path.isfile(self.object_path): container_path = os.path.join( os.path.dirname(self.object_path), path.split('/', 1)[0]) container_path = normalize_path(container_path) if container_path == self.object_path: path = path.split('/', 1)[1] fid = FormatIdentifier(allow_unknown_file_types=True) content_type = fid.get_mimetype(path) return generate_file_response(self.open_file(path, 'rb'), content_type, force_download=force_download, name=path) except (IOError, OSError) as e: if e.errno == errno.ENOENT: raise exceptions.NotFound # Windows raises PermissionDenied (errno.EACCES) when trying to use # open() on a directory if os.name == 'nt': if e.errno not in (errno.EACCES, errno.EISDIR): raise elif e.errno != errno.EISDIR: raise except IndexError: if force_download: fid = FormatIdentifier(allow_unknown_file_types=True) content_type = fid.get_mimetype(path) return generate_file_response(self.open_file( self.object_path, 'rb'), content_type, force_download=force_download, name=path) entries = self.list_files(path) if paginator is not None: paginated = paginator.paginate_queryset(entries, request) return paginator.get_paginated_response(paginated) return Response(entries)
def test_gzipped_file(self, mock_mimetypes_init): fid = FormatIdentifier(allow_unknown_file_types=True) self.assertEqual(fid.get_mimetype('foo.tar.gz'), 'application/gzip')
def list_files(path, force_download=False, request=None, paginator=None): if isinstance(path, list): if paginator is not None: paginated = paginator.paginate_queryset(path, request) return paginator.get_paginated_response(paginated) return Response(path) fid = FormatIdentifier(allow_unknown_file_types=True) path = path.rstrip('/ ') if os.path.isfile(path): if tarfile.is_tarfile(path): with tarfile.open(path) as tar: entries = [] for member in tar.getmembers(): if not member.isfile(): continue entries.append({ "name": member.name, "type": 'file', "size": member.size, "modified": timestamp_to_datetime(member.mtime), }) if paginator is not None: paginated = paginator.paginate_queryset(entries, request) return paginator.get_paginated_response(paginated) return Response(entries) elif zipfile.is_zipfile(path) and os.path.splitext(path)[1] == '.zip': with zipfile.ZipFile(path) as zipf: entries = [] for member in zipf.filelist: if member.filename.endswith('/'): continue entries.append({ "name": member.filename, "type": 'file', "size": member.file_size, "modified": datetime(*member.date_time), }) if paginator is not None: paginated = paginator.paginate_queryset(entries, request) return paginator.get_paginated_response(paginated) return Response(entries) content_type = fid.get_mimetype(path) return generate_file_response(open(path, 'rb'), content_type, force_download) if os.path.isdir(path): entries = [] for entry in sorted(get_files_and_dirs(path), key=lambda x: x.name): entry_type = "dir" if entry.is_dir() else "file" size, _ = get_tree_size_and_count(entry.path) entries.append( { "name": os.path.basename(entry.path), "type": entry_type, "size": size, "modified": timestamp_to_datetime(entry.stat().st_mtime), } ) if paginator is not None and request is not None: paginated = paginator.paginate_queryset(entries, request) return paginator.get_paginated_response(paginated) if len(path.split('.tar/')) == 2: tar_path, tar_subpath = path.split('.tar/') tar_path += '.tar' with tarfile.open(tar_path) as tar: try: f = io.BytesIO(tar.extractfile(tar_subpath).read()) content_type = fid.get_mimetype(tar_subpath) return generate_file_response(f, content_type, force_download, name=tar_subpath) except KeyError: raise NotFound if len(path.split('.zip/')) == 2: zip_path, zip_subpath = path.split('.zip/') zip_path += '.zip' with zipfile.ZipFile(zip_path) as zipf: try: f = io.BytesIO(zipf.read(zip_subpath)) content_type = fid.get_mimetype(zip_subpath) return generate_file_response(f, content_type, force_download, name=zip_subpath) except KeyError: raise NotFound raise NotFound
def test_unknown_content_type_when_not_allowed_should_raise_exception( self, mock_mimetypes_init): fid = FormatIdentifier(allow_unknown_file_types=False) with self.assertRaises(FileFormatNotAllowed): fid.get_mimetype('some_random_file')
def test_unknown_content_type(self, mock_mimetypes_init): fid = FormatIdentifier(allow_unknown_file_types=True) self.assertEqual(fid.get_mimetype('some_random_file'), DEFAULT_MIMETYPE)