libarchive.js

repository·master·Indexed 43 days ago

https://github.com/nika-begiashvili/libarchivejs

A WebAssembly port of the libarchive C library for high-performance archive extraction and creation in browsers and Node.js. Version 2.0.2 supports formats including ZIP, 7-Zip, RAR, and TAR. It provides the ArchiveReader class for inspecting and extracting files, and Archive.write() for creating new archives with configurable compression and formats.

Tokens
3.5K
Snippets
15
Records
19
Agent score
56%

What's inside libarchive.js

  1. Initialize libarchive.js in the browser

    master

    Libarchivejs consists of an ES module (the interface) and a webworker bundle. Because the webworker bundle is not automatically bundled by most bundlers, you must ensure it is available in your public folder and specify its path using Archive.init().

    Note: If the libarchive.js file is in the same directory as the bundle file, you do not need to call Archive.init().

    import {Archive} from 'libarchive.js/main.js';
    
    Archive.init({
        workerUrl: 'libarchive.js/dist/worker-bundle.js'
    });
  2. Use libarchive.js in Node.js

    master

    To use the library in a Node.js environment, import from the specific Node.js entry point: libarchivejs/dist/libarchive-node.mjs.

    When creating archives in Node.js, you must wrap your buffers in a Blob and ensure every file in the files array includes a pathname.

    import { Archive, ArchiveCompression, ArchiveFormat } from "libarchivejs/dist/libarchive-node.mjs";
    import fs from 'fs';
    
    let buffer = fs.readFileSync("test/files/archives/README.md");
    let blob = new Blob([buffer]);
    
    const archiveFile = await Archive.write({
      files: [{
        file: blob,
        pathname: "README.md",
      }],
      outputFileName: "test.tar.gz",
      compression: ArchiveCompression.GZIP,
      format: ArchiveFormat.USTAR,
      passphrase: null,
    });
  3. Handle encrypted archives

    master

    Libarchivejs provides methods to check for and handle encrypted data.

    1. Check for encryption: Use hasEncryptedData(). It returns true if encrypted, false if not, or null if the status cannot be determined.
    2. Provide password: Use usePassword(password) before attempting extraction.
    const archive = await Archive.open(file);
    
    // Check encryption
    const isEncrypted = await archive.hasEncryptedData();
    
    // If encrypted, provide password
    if (isEncrypted) {
        await archive.usePassword("password");
    }
    
    let obj = await archive.extractFiles();
  4. Extract a single file from an archive

    master

    To extract only one specific file, use getFilesObject() to get the file list, then call .extract() on the specific CompressedFile object.

    const filesObj = await archive.getFilesObject();
    const file = await filesObj['.gitignore'].extract();
  5. Create a new archive

    master

    Use Archive.write() to create a new archive.

    Important Requirements:

    • In the browser, pathname is optional.
    • In Node.js, pathname is required for each file in the files array.

    Options Object:

    • files: Array of { file: Blob|File, pathname: string }.
    • outputFileName: The name of the resulting archive.
    • compression: An ArchiveCompression enum value (e.g., ArchiveCompression.GZIP).
    • format: An ArchiveFormat enum value (e.g., ArchiveFormat.USTAR).
    • passphrase: Optional string for encrypted archives.
    const archiveFile = await Archive.write({
        files: [
            { file: file, pathname: 'folder/file.zip' }
        ],
        outputFileName: "test.tar.gz",
        compression: ArchiveCompression.GZIP,
        format: ArchiveFormat.USTAR,
        passphrase: null,
    });
  6. Extract all files from an archive

    master

    To extract all files from an archive, open the file with Archive.open() and then call extractFiles(). This method returns an object where keys are file paths and values are File objects.

    You can also pass a callback to extractFiles to track progress as each file is extracted.

    Returns: An object mapping paths to File objects.

    Example output:

    {
        ".gitignore": {File},
        "addon": {
            "addon.py": {File},
            "addon.xml": {File}
        },
        "README.md": {File}
    }
    import {Archive} from 'libarchive.js/main.js';
    
    // ... init code ...
    
    const archive = await Archive.open(file);
    let obj = await archive.extractFiles();
    
    // With progress tracking:
    archive.extractFiles((entry) => { // { file: {File}, path: {String} }
        console.log(entry);
    });
  7. List archive contents without decompressing

    master

    If you need to inspect the archive contents without the overhead of full decompression, use getFilesObject() or getFilesArray(). If these are called after extractFiles(), they will return the actual extracted files instead of compressed placeholders.

    // Returns an object mapping paths to {CompressedFile}
    await archive.getFilesObject();
    
    // Returns an array of {file: {CompressedFile}, path: string}
    await archive.getFilesArray();
  8. Extract files from an archive

    master

    You can extract files from an archive using two primary methods depending on whether you want a single file or the entire contents.

    Extract a single file

    Use extractSingleFile(target: string) to extract one specific file by its path within the archive. It returns a standard JavaScript File object.

    Extract all files

    Use extractFiles(extractCallback?: Function) to extract all files in the archive.

    • If an extractCallback is provided, it will be called for each extracted file with an object containing { file: File, path: string }.
    • This method automatically terminates the worker once extraction is complete.
    • It returns an object representing the directory structure containing the extracted File objects.
    // Extracting a single file
    const singleFile = await reader.extractSingleFile('folder/image.png');
    
    // Extracting all files with a callback
    await reader.extractFiles(({ file, path }) => {
      console.log(`Extracted ${path}`);
    });
  9. Inspect archive structure with getFilesObject

    master

    The getFilesObject() method returns a nested object representing the archive's directory structure.

    • For entries where type === 'FILE', the object will contain a CompressedFile instance at that path.
    • CompressedFile allows you to access metadata and eventually extract the file content.
    • If you prefer a flat list, you can use getFilesArray() which converts the directory object into an array of entries.
    // Get directory structure
    const structure = await reader.getFilesObject();
    
    // Get flat array of entries
    const filesArray = await reader.getFilesArray();
  10. Create a new archive with Archive.write()

    master

    Use Archive.write() to bundle multiple files into a new archive. This method returns a new Web File object containing the archive data.

    import { Archive, ArchiveCompression, ArchiveFormat } from 'libarchivejs';
    
    const newFile = await Archive.write({
      files: [
        { file: file1, pathname: 'folder/file1.txt' },
        { file: file2, pathname: 'file2.txt' }
      ],
      outputFileName: 'my-archive.tar.gz',
      compression: ArchiveCompression.Gzip,
      format: ArchiveFormat.Tar,
      passphrase: null // or a string if the format supports encryption
    });
  11. Initialize libarchivejs with Archive.init()

    master

    Before performing archive operations, you can globally configure libarchivejs using Archive.init(). This is useful for specifying a custom worker URL or providing custom worker/client creation logic. If not called, the library uses default settings.

    import { Archive } from 'libarchivejs';
    
    Archive.init({
      workerUrl: '/path/to/your/worker-bundle.js',
      // or provide custom worker/client logic
      getWorker: () => new Worker('custom-worker.js'),
      createClient: (worker) => {
        // custom client implementation
      }
    });