What are the best practices for handling file uploads and downloads in PHP to prevent security vulnerabilities?

File uploads and downloads in PHP can introduce security vulnerabilities if not handled properly. To prevent issues such as file injection or execution, it is important to validate and sanitize user input, limit file types and sizes, store files outside of the web root directory, and use secure file permissions. Additionally, it is recommended to use libraries like Symfony's HTTP Foundation for handling file uploads securely.

// Example of handling file uploads securely using Symfony's HTTP Foundation
use Symfony\Component\HttpFoundation\File\UploadedFile;

// Validate and sanitize file input
if ($_FILES['file']['error'] === UPLOAD_ERR_OK) {
    $file = new UploadedFile($_FILES['file']['tmp_name'], $_FILES['file']['name'], $_FILES['file']['type'], $_FILES['file']['size'], $_FILES['file']['error']);
    
    // Limit file types and sizes
    $allowedTypes = ['image/jpeg', 'image/png'];
    $maxSize = 1048576; // 1MB
    
    if (in_array($file->getClientMimeType(), $allowedTypes) && $file->getSize() <= $maxSize) {
        // Store files outside of the web root directory
        $file->move('/path/to/uploads', $file->getClientOriginalName());
    } else {
        echo 'Invalid file type or size.';
    }
} else {
    echo 'Error uploading file.';
}