Skip to content

Conversation

vadasziattila
Copy link
Contributor

this change resolves #744 by adding the option to able to download multiple files, folders and browse while downloading.
Signed-off-by: Vadászi Attila vadaszi.attila@bitecode.hu

@prasathmani
Copy link
Owner

@ner00 can you review this PR.

@ner00
Copy link
Contributor

ner00 commented Oct 16, 2024

@ner00 can you review this PR.

Looks good, works nicely.
Thanks @vadasziattila!

@ner00
Copy link
Contributor

ner00 commented Oct 16, 2024

I just have one question, maybe you guys can help me out.
I always used FM_Zipper because it was already there and I customized it to a specific compression level... I'm having trouble doing the same for the code in this PR. Here's an example:

// Add the file to the ZIP archive
$zip->addFile($new_path, basename($new_path));
$zip->setCompressionName($f, ZipArchive::CM_STORE); // Setting 'Store' as compression level

This works, but if I have sub-folders with other files, those files will always be compressed as Deflate instead of Store. I've been trying to understand why the files in the sub-folders do not respect the setCompressionName.

EDIT: I think I figured it out, the first foreach that recurses through files and folders goes like this:

if (is_file($fullPath)) {
    // Add the file to the ZIP archive
    $zipArchive->addFile($fullPath, $zipPath . '/' . $file);
    $zipArchive->setCompressionName($zipPath . '/' . $file, ZipArchive::CM_STORE);
}

Copy link
Contributor

@ner00 ner00 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

LGTM

@prasathmani
Copy link
Owner

@vadasziattila Download is not working when select the folder

Copy link
Owner

@prasathmani prasathmani left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Download is not working when select the folder

@ner00
Copy link
Contributor

ner00 commented Oct 19, 2024

Download is not working when select the folder

It's definitely working on my end, either only files or only folders, or both.
Are we testing the same code even?

Here in full:

// Mass downloading
if (isset($_POST['group'], $_POST['download'], $_POST['token']) && !FM_READONLY) {

    // Verify token to ensure it's valid
    if (!verifyToken($_POST['token'])) {
        fm_set_msg(lng("Invalid Token."), 'error');
        exit;
    }

    $path = FM_ROOT_PATH;
    if (FM_PATH != '') {
        $path .= '/' . FM_PATH;
    }

    $errors = 0;
    $files = $_POST['file']; // List of selected files and folders
    if (is_array($files) && count($files)) {

        // Create a new ZIP archive
        $zip = new ZipArchive();
        $zip_filename = 'download_' . date('Y-m-d_H-i-s') . '.zip';
        $zip_filepath = sys_get_temp_dir() . '/' . $zip_filename;

        if ($zip->open($zip_filepath, ZipArchive::CREATE) !== TRUE) {
            fm_set_msg(lng('Cannot create ZIP file'), 'error');
            $FM_PATH = FM_PATH; 
            fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
        }

        // Function to recursively add folders and files to the ZIP archive, including empty folders
        function addFolderToZip($folderPath, $zipArchive, $zipPath) {
            $files = scandir($folderPath);

            // Ensure the folder itself is added to the ZIP (even if empty)
            $zipArchive->addEmptyDir($zipPath);

            foreach ($files as $file) {
                if ($file == '.' || $file == '..') continue;
                $fullPath = $folderPath . '/' . $file;
                if (is_file($fullPath)) {
                    // Add the file to the ZIP archive
                    $zipArchive->addFile($fullPath, $zipPath . '/' . $file);
                } elseif (is_dir($fullPath)) {
                    // Recursively add folders (including empty folders)
                    addFolderToZip($fullPath, $zipArchive, $zipPath . '/' . $file);
                }
            }
        }

        foreach ($files as $f) {
            if ($f != '') {
                $new_path = $path . '/' . fm_clean_path($f); // Sanitize the file path

                if (is_file($new_path)) {
                    // Add the file to the ZIP archive
                    $zip->addFile($new_path, basename($new_path));
                } elseif (is_dir($new_path)) {
                    // Add the folder and its contents to the ZIP archive (including empty folders)
                    addFolderToZip($new_path, $zip, basename($new_path));
                } else {
                    $errors++;
                }
            }
        }

        // Close the ZIP archive
        $zip->close();

        // Check for errors
        if ($errors == 0) {
            // Serve the ZIP file for download
            if (file_exists($zip_filepath)) {
                header('Content-Type: application/zip');
                header('Content-Disposition: attachment; filename="' . $zip_filename . '"');
                header('Content-Length: ' . filesize($zip_filepath));
                readfile($zip_filepath);
                // Remove the ZIP file from the temporary directory after download
                unlink($zip_filepath);
                exit;
            } else {
                fm_set_msg(lng('Error creating ZIP file'), 'error');
            }
        } else {
            fm_set_msg(lng('Error while adding items to ZIP'), 'error');
        }
    } else {
        fm_set_msg(lng('Nothing selected'), 'alert');
    }

    $FM_PATH = FM_PATH; 
    fm_redirect(FM_SELF_URL . '?p=' . urlencode($FM_PATH));
}

Copy link
Contributor

@ner00 ner00 left a comment

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Works fine for me.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

Can download only one file at a time / cannot browse while downloading

3 participants