Skip to content

Zipping and unzipping

ADM can pack a document or an entire folder tree into a .zip, and expand an uploaded .zip back into folders and documents.

declare
l_zip_id number;
begin
adm_context_api.system_user_login('JDOE');
l_zip_id := adm_zip_api.zip_document(
p_document_id => l_document_id
);
commit;
end;
/

The archive is named after the document with the extension replaced — report.pdf becomes report.zip — and holds one entry under the document’s own name. It is created in the document’s own folder unless you pass p_target_folder_id, and you need edit rights on wherever it is created.

l_zip_id := adm_zip_api.zip_folder(
p_folder_id => l_folder_id
, p_target_folder_id => l_target_folder_id -- defaults to the folder's parent
);

The archive lands next to the folder, in its parent, the way a desktop file manager does it — not inside the folder it is a copy of. Two cases keep the archive in the folder itself, because there is nowhere beside it to put one: the repository root, which has no parent, and a home folder, whose parent is the system folder /users that its owner may read but not write. An explicit p_target_folder_id overrules all of it, and you need edit rights on wherever the archive is created.

Entry paths are relative to the folder you zipped, so a document in child/grandchild ends up at child/grandchild/report.pdf — not under the folder’s absolute path.

Skipped without an error: trashed subfolders, trashed documents, archived documents, and anything the caller may not view. The read side runs under the caller’s own permissions, so two users zipping the same folder can legitimately get different archives. If nothing readable is found at all, the call fails rather than producing an empty archive.

Nothing is ever overwritten. Zipping the same folder twice gives you projects.zip and then projects_restored.zip.

declare
l_folder_id number;
begin
adm_context_api.system_user_login('JDOE');
l_folder_id := adm_zip_api.unzip_document(
p_document_id => l_zip_document_id
);
commit; -- see the transaction note below
end;
/

A folder named after the archive is created next to it, and the structure inside is recreated below it. Three behaviours:

  • A redundant top-level directory is dropped. If every entry sits under one common directory — which is what desktop zip tools produce — you get projects/..., not projects/projects/....
  • Existing folders are reused, not duplicated. A document name that is already taken gets a free one rather than overwriting.
  • Unsafe entry paths fail the whole call. An absolute path, a drive letter or any .. segment is rejected outright rather than sanitised: a sanitised path would silently write somewhere the archive did not name.
GuardValue
Entries per archive5,000
Total uncompressed size2 GiB
Size of a produced archive2 GiB

These are constants in adm_zip_api, not rows in adm_settings: they bound what one call can do to shared storage. Any user with edit rights can unzip, so a crafted archive that decompresses to hundreds of times its own size must not be able to fill your tablespace. unzip_document accepts p_max_entries and p_max_extracted_bytes if you want to be stricter for a particular call.

The extracted-size guard is checked before anything is written, so an archive that is too large fails without leaving a half-expanded tree behind.

All of these are raised as named exceptions on adm_error — see Error handling.

SituationError
The document is not a zip filec_err_not_an_archive
The archive holds no files, or the folder had nothing readablec_err_archive_empty
An entry path is absolute or contains ..c_err_invalid_name
Any guard exceededc_err_limit_exceeded
No rights on the source, or on the destination folderc_err_no_view_right, c_err_no_edit_right
The target is the trash folderc_err_folder_trash_rule