mirror of
https://github.com/paperless-ngx/paperless-ngx.git
synced 2025-04-09 09:58:20 -05:00
add no-archive and no-thumbnail options to administration exporter and importer
This commit is contained in:
parent
c7690c05f5
commit
9ae186e6f9
@ -227,12 +227,14 @@ is not a TTY" errors. For example:
|
|||||||
`docker-compose exec -T webserver document_exporter ../export`
|
`docker-compose exec -T webserver document_exporter ../export`
|
||||||
|
|
||||||
```
|
```
|
||||||
document_exporter target [-c] [-f] [-d]
|
document_exporter target [-c] [-f] [-d] [-na] [-nt]
|
||||||
|
|
||||||
optional arguments:
|
optional arguments:
|
||||||
-c, --compare-checksums
|
-c, --compare-checksums
|
||||||
-f, --use-filename-format
|
-f, --use-filename-format
|
||||||
-d, --delete
|
-d, --delete
|
||||||
|
-na, --no-archive
|
||||||
|
-nt, --no-thumbnail
|
||||||
-z --zip
|
-z --zip
|
||||||
```
|
```
|
||||||
|
|
||||||
@ -259,6 +261,14 @@ current export such as files from deleted documents, specify `--delete`.
|
|||||||
Be careful when pointing paperless to a directory that already contains
|
Be careful when pointing paperless to a directory that already contains
|
||||||
other files.
|
other files.
|
||||||
|
|
||||||
|
Paperless will not export archive files if you use `--no-archive`, or will
|
||||||
|
not export thumbnails if you use `--no-thumbnail`. After importing, These
|
||||||
|
files can be generated again by using `document_archiver` or
|
||||||
|
`document_thumbnails`. It can make sense to omit these files from backup
|
||||||
|
as their content and checksum can change (new archiver or thumbnail
|
||||||
|
generator algorithm) and may then cause additional used space in
|
||||||
|
a deduplicated backup.
|
||||||
|
|
||||||
If `-z` or `--zip` is provided, the export will be a zipfile
|
If `-z` or `--zip` is provided, the export will be a zipfile
|
||||||
in the target directory, named according to the current date.
|
in the target directory, named according to the current date.
|
||||||
|
|
||||||
|
@ -82,6 +82,21 @@ class Command(BaseCommand):
|
|||||||
"deleted documents.",
|
"deleted documents.",
|
||||||
)
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-na",
|
||||||
|
"--no-archive",
|
||||||
|
default=False,
|
||||||
|
action="store_true",
|
||||||
|
help="Avoid exporting archive files",
|
||||||
|
)
|
||||||
|
|
||||||
|
parser.add_argument(
|
||||||
|
"-nt",
|
||||||
|
"--no-thumbnail",
|
||||||
|
default=False,
|
||||||
|
action="store_true",
|
||||||
|
help="Avoid exporting thumbnail files",
|
||||||
|
)
|
||||||
parser.add_argument(
|
parser.add_argument(
|
||||||
"--no-progress-bar",
|
"--no-progress-bar",
|
||||||
default=False,
|
default=False,
|
||||||
@ -105,6 +120,8 @@ class Command(BaseCommand):
|
|||||||
self.compare_checksums = False
|
self.compare_checksums = False
|
||||||
self.use_filename_format = False
|
self.use_filename_format = False
|
||||||
self.delete = False
|
self.delete = False
|
||||||
|
self.no_archive = False
|
||||||
|
self.no_thumbnail = False
|
||||||
|
|
||||||
def handle(self, *args, **options):
|
def handle(self, *args, **options):
|
||||||
|
|
||||||
@ -112,6 +129,8 @@ class Command(BaseCommand):
|
|||||||
self.compare_checksums = options["compare_checksums"]
|
self.compare_checksums = options["compare_checksums"]
|
||||||
self.use_filename_format = options["use_filename_format"]
|
self.use_filename_format = options["use_filename_format"]
|
||||||
self.delete = options["delete"]
|
self.delete = options["delete"]
|
||||||
|
self.no_archive = options["no_archive"]
|
||||||
|
self.no_thumbnail = options["no_thumbnail"]
|
||||||
zip_export: bool = options["zip"]
|
zip_export: bool = options["zip"]
|
||||||
|
|
||||||
# If zipping, save the original target for later and
|
# If zipping, save the original target for later and
|
||||||
@ -246,11 +265,14 @@ class Command(BaseCommand):
|
|||||||
original_target = (self.target / Path(original_name)).resolve()
|
original_target = (self.target / Path(original_name)).resolve()
|
||||||
document_dict[EXPORTER_FILE_NAME] = original_name
|
document_dict[EXPORTER_FILE_NAME] = original_name
|
||||||
|
|
||||||
|
if not self.no_thumbnail:
|
||||||
thumbnail_name = base_name + "-thumbnail.webp"
|
thumbnail_name = base_name + "-thumbnail.webp"
|
||||||
thumbnail_target = (self.target / Path(thumbnail_name)).resolve()
|
thumbnail_target = (self.target / Path(thumbnail_name)).resolve()
|
||||||
document_dict[EXPORTER_THUMBNAIL_NAME] = thumbnail_name
|
document_dict[EXPORTER_THUMBNAIL_NAME] = thumbnail_name
|
||||||
|
else:
|
||||||
|
thumbnail_target = None
|
||||||
|
|
||||||
if document.has_archive_version:
|
if not self.no_archive and document.has_archive_version:
|
||||||
archive_name = base_name + "-archive.pdf"
|
archive_name = base_name + "-archive.pdf"
|
||||||
archive_target = (self.target / Path(archive_name)).resolve()
|
archive_target = (self.target / Path(archive_name)).resolve()
|
||||||
document_dict[EXPORTER_ARCHIVE_NAME] = archive_name
|
document_dict[EXPORTER_ARCHIVE_NAME] = archive_name
|
||||||
@ -266,6 +288,7 @@ class Command(BaseCommand):
|
|||||||
original_target.write_bytes(GnuPG.decrypted(out_file))
|
original_target.write_bytes(GnuPG.decrypted(out_file))
|
||||||
os.utime(original_target, times=(t, t))
|
os.utime(original_target, times=(t, t))
|
||||||
|
|
||||||
|
if thumbnail_target:
|
||||||
thumbnail_target.parent.mkdir(parents=True, exist_ok=True)
|
thumbnail_target.parent.mkdir(parents=True, exist_ok=True)
|
||||||
with document.thumbnail_file as out_file:
|
with document.thumbnail_file as out_file:
|
||||||
thumbnail_target.write_bytes(GnuPG.decrypted(out_file))
|
thumbnail_target.write_bytes(GnuPG.decrypted(out_file))
|
||||||
@ -283,6 +306,7 @@ class Command(BaseCommand):
|
|||||||
original_target,
|
original_target,
|
||||||
)
|
)
|
||||||
|
|
||||||
|
if thumbnail_target:
|
||||||
self.check_and_copy(document.thumbnail_path, None, thumbnail_target)
|
self.check_and_copy(document.thumbnail_path, None, thumbnail_target)
|
||||||
|
|
||||||
if archive_target:
|
if archive_target:
|
||||||
|
@ -193,8 +193,11 @@ class Command(BaseCommand):
|
|||||||
doc_file = record[EXPORTER_FILE_NAME]
|
doc_file = record[EXPORTER_FILE_NAME]
|
||||||
document_path = os.path.join(self.source, doc_file)
|
document_path = os.path.join(self.source, doc_file)
|
||||||
|
|
||||||
|
if EXPORTER_THUMBNAIL_NAME in record:
|
||||||
thumb_file = record[EXPORTER_THUMBNAIL_NAME]
|
thumb_file = record[EXPORTER_THUMBNAIL_NAME]
|
||||||
thumbnail_path = Path(os.path.join(self.source, thumb_file)).resolve()
|
thumbnail_path = Path(os.path.join(self.source, thumb_file)).resolve()
|
||||||
|
else:
|
||||||
|
thumbnail_path = None
|
||||||
|
|
||||||
if EXPORTER_ARCHIVE_NAME in record:
|
if EXPORTER_ARCHIVE_NAME in record:
|
||||||
archive_file = record[EXPORTER_ARCHIVE_NAME]
|
archive_file = record[EXPORTER_ARCHIVE_NAME]
|
||||||
@ -212,6 +215,7 @@ class Command(BaseCommand):
|
|||||||
|
|
||||||
shutil.copy2(document_path, document.source_path)
|
shutil.copy2(document_path, document.source_path)
|
||||||
|
|
||||||
|
if thumbnail_path:
|
||||||
if thumbnail_path.suffix in {".png", ".PNG"}:
|
if thumbnail_path.suffix in {".png", ".PNG"}:
|
||||||
run_convert(
|
run_convert(
|
||||||
density=300,
|
density=300,
|
||||||
@ -225,6 +229,7 @@ class Command(BaseCommand):
|
|||||||
)
|
)
|
||||||
else:
|
else:
|
||||||
shutil.copy2(thumbnail_path, document.thumbnail_path)
|
shutil.copy2(thumbnail_path, document.thumbnail_path)
|
||||||
|
|
||||||
if archive_path:
|
if archive_path:
|
||||||
create_source_path_directory(document.archive_path)
|
create_source_path_directory(document.archive_path)
|
||||||
# TODO: this assumes that the export is valid and
|
# TODO: this assumes that the export is valid and
|
||||||
|
@ -102,6 +102,8 @@ class TestExportImport(DirectoriesMixin, TestCase):
|
|||||||
use_filename_format=False,
|
use_filename_format=False,
|
||||||
compare_checksums=False,
|
compare_checksums=False,
|
||||||
delete=False,
|
delete=False,
|
||||||
|
no_archive=False,
|
||||||
|
no_thumbnail=False,
|
||||||
):
|
):
|
||||||
args = ["document_exporter", self.target]
|
args = ["document_exporter", self.target]
|
||||||
if use_filename_format:
|
if use_filename_format:
|
||||||
@ -110,6 +112,10 @@ class TestExportImport(DirectoriesMixin, TestCase):
|
|||||||
args += ["--compare-checksums"]
|
args += ["--compare-checksums"]
|
||||||
if delete:
|
if delete:
|
||||||
args += ["--delete"]
|
args += ["--delete"]
|
||||||
|
if no_archive:
|
||||||
|
args += ["--no-archive"]
|
||||||
|
if no_thumbnail:
|
||||||
|
args += ["--no-thumbnail"]
|
||||||
|
|
||||||
call_command(*args)
|
call_command(*args)
|
||||||
|
|
||||||
@ -497,3 +503,63 @@ class TestExportImport(DirectoriesMixin, TestCase):
|
|||||||
call_command(*args)
|
call_command(*args)
|
||||||
|
|
||||||
self.assertEqual("That path doesn't appear to be writable", str(e))
|
self.assertEqual("That path doesn't appear to be writable", str(e))
|
||||||
|
|
||||||
|
def test_no_archive(self):
|
||||||
|
shutil.rmtree(os.path.join(self.dirs.media_dir, "documents"))
|
||||||
|
shutil.copytree(
|
||||||
|
os.path.join(os.path.dirname(__file__), "samples", "documents"),
|
||||||
|
os.path.join(self.dirs.media_dir, "documents"),
|
||||||
|
)
|
||||||
|
|
||||||
|
manifest = self._do_export()
|
||||||
|
has_archive = False
|
||||||
|
for element in manifest:
|
||||||
|
if element["model"] == "documents.document":
|
||||||
|
has_archive = (
|
||||||
|
has_archive or document_exporter.EXPORTER_ARCHIVE_NAME in element
|
||||||
|
)
|
||||||
|
self.assertTrue(has_archive)
|
||||||
|
|
||||||
|
has_archive = False
|
||||||
|
manifest = self._do_export(no_archive=True)
|
||||||
|
for element in manifest:
|
||||||
|
if element["model"] == "documents.document":
|
||||||
|
has_archive = (
|
||||||
|
has_archive or document_exporter.EXPORTER_ARCHIVE_NAME in element
|
||||||
|
)
|
||||||
|
self.assertFalse(has_archive)
|
||||||
|
|
||||||
|
with paperless_environment() as dirs:
|
||||||
|
call_command("document_importer", self.target)
|
||||||
|
self.assertEqual(Document.objects.count(), 4)
|
||||||
|
|
||||||
|
def test_no_thumbnail(self):
|
||||||
|
shutil.rmtree(os.path.join(self.dirs.media_dir, "documents"))
|
||||||
|
shutil.copytree(
|
||||||
|
os.path.join(os.path.dirname(__file__), "samples", "documents"),
|
||||||
|
os.path.join(self.dirs.media_dir, "documents"),
|
||||||
|
)
|
||||||
|
|
||||||
|
manifest = self._do_export()
|
||||||
|
has_thumbnail = False
|
||||||
|
for element in manifest:
|
||||||
|
if element["model"] == "documents.document":
|
||||||
|
has_thumbnail = (
|
||||||
|
has_thumbnail
|
||||||
|
or document_exporter.EXPORTER_THUMBNAIL_NAME in element
|
||||||
|
)
|
||||||
|
self.assertTrue(has_thumbnail)
|
||||||
|
|
||||||
|
has_thumbnail = False
|
||||||
|
manifest = self._do_export(no_thumbnail=True)
|
||||||
|
for element in manifest:
|
||||||
|
if element["model"] == "documents.document":
|
||||||
|
has_thumbnail = (
|
||||||
|
has_thumbnail
|
||||||
|
or document_exporter.EXPORTER_THUMBNAIL_NAME in element
|
||||||
|
)
|
||||||
|
self.assertFalse(has_thumbnail)
|
||||||
|
|
||||||
|
with paperless_environment() as dirs:
|
||||||
|
call_command("document_importer", self.target)
|
||||||
|
self.assertEqual(Document.objects.count(), 4)
|
||||||
|
Loading…
x
Reference in New Issue
Block a user