实现加密压缩文件解密后解压再下载的PHP功能求助
Solution: Add Decompression Before Download
Got it, let's fix this up. Your current workflow decrypts the file but leaves it in a compressed state—we need to unpack that compressed data first before sending it to the user. Here's the modified Download function with decompression logic added, and I'll break down the key changes below:
function Download($path, $type, $key, $iv) { if ($type == "File") { if (file_exists($path)) { // Step 1: Read and decrypt the original encrypted file $fileBuffer = file_get_contents($path); $iv = str_pad($iv, 16, "\0"); $cipher = base64_decode($fileBuffer); $compressedData = openssl_decrypt($cipher, "AES-256-CBC", $key, OPENSSL_RAW_DATA, $iv); // Step 2: Decompress the decrypted data using ZipArchive $tempZipPath = sys_get_temp_dir() . '/' . uniqid('temp_zip_', true); file_put_contents($tempZipPath, $compressedData); $zip = new ZipArchive(); $extractSuccess = $zip->open($tempZipPath); if ($extractSuccess === true) { // Assume the zip contains a single file (matches your original extension requirement) $extractedFileName = $zip->getNameIndex(0); $extractedFilePath = sys_get_temp_dir() . '/' . $extractedFileName; // Extract the file to temp directory $zip->extractTo(sys_get_temp_dir()); $zip->close(); // Step 3: Send the extracted file to the user for download header('Content-Description: File Transfer'); header('Content-Type: application/octet-stream'); header('Content-Disposition: attachment; filename="' . basename($extractedFileName) . '"'); header('Expires: 0'); header('Cache-Control: must-revalidate'); header('Pragma: public'); header('Content-Length: ' . filesize($extractedFilePath)); readfile($extractedFilePath); // Clean up temporary files unlink($tempZipPath); unlink($extractedFilePath); } else { // Handle decompression failure (send error or fallback) header("HTTP/1.1 500 Internal Server Error"); echo "Failed to decompress the file. Error code: " . $extractSuccess; unlink($tempZipPath); exit; } // Step 4: Re-encrypt the original file to keep it secure (your original logic) $fileBuffer = file_get_contents($path); $iv = str_pad($iv, 16, "\0"); $cipher = openssl_encrypt($fileBuffer, "AES-256-CBC", $key, OPENSSL_RAW_DATA, $iv); $cipher64 = base64_encode($cipher); file_put_contents($path, $cipher64); exit; } else { header("HTTP/1.1 404 Not Found"); echo "File not found."; exit; } } }
Key Changes Explained:
- Avoid modifying the original file mid-process: Instead of writing decrypted compressed data back to
$path, we use temporary files to handle decompression—this keeps your original encrypted file untouched until we re-encrypt it at the end. - ZipArchive for decompression: We write the decrypted compressed data to a temporary zip file (even though it doesn't have a
.zipextension, the content is still zip-formatted), then useZipArchiveto extract the actual file inside. - Temp file cleanup: After downloading, we delete the temporary zip and extracted files to avoid cluttering the server.
- Error handling: Added basic checks for decompression failures and missing files, so users get clear feedback instead of a broken download.
- Preserve original workflow: The final re-encryption step from your original function is kept intact, so your stored file remains encrypted after the download.
Notes:
- This assumes your compressed archive contains a single file (since you want to retain the original extension). If you might have multiple files in the archive, you'll need to adjust the logic to handle that (e.g., zip them back up for download, or let the user pick which file to download).
- Make sure the
ZipArchiveextension is enabled on your PHP server—most hosting environments have it enabled by default, but you can check withphpinfo().
内容的提问来源于stack exchange,提问作者MIYUKI NARAHARA
相关产品推荐
相关产品推荐

