72 lines
2.2 KiB
PHP
72 lines
2.2 KiB
PHP
<?php
|
|
|
|
namespace App\Support;
|
|
|
|
use Illuminate\Support\Facades\Storage;
|
|
use Illuminate\Support\Str;
|
|
use Symfony\Component\HttpFoundation\Response;
|
|
|
|
class DownloadFile
|
|
{
|
|
/**
|
|
* Create a download response with UTF-8 filename support.
|
|
*/
|
|
public static function fromDisk(
|
|
string $disk,
|
|
string $path,
|
|
string $downloadName,
|
|
array $headers = []
|
|
): Response {
|
|
$safeName = static::asciiFallbackFilename($downloadName);
|
|
$response = Storage::disk($disk)->download($path, $safeName, $headers);
|
|
$response->headers->set('Content-Disposition', static::contentDisposition($downloadName));
|
|
|
|
return $response;
|
|
}
|
|
|
|
/**
|
|
* Build RFC 5987 compatible Content-Disposition value.
|
|
*/
|
|
public static function contentDisposition(
|
|
string $downloadName,
|
|
string $type = 'attachment'
|
|
): string {
|
|
$safeOriginalName = static::sanitizeHeaderFilename($downloadName);
|
|
$safeFallback = addcslashes(static::asciiFallbackFilename($safeOriginalName), "\"\\");
|
|
$encoded = rawurlencode($safeOriginalName);
|
|
|
|
return "{$type}; filename=\"{$safeFallback}\"; filename*=UTF-8''{$encoded}";
|
|
}
|
|
|
|
/**
|
|
* Generate ASCII fallback filename for old clients.
|
|
*/
|
|
public static function asciiFallbackFilename(string $filename): string
|
|
{
|
|
$filename = static::sanitizeHeaderFilename($filename);
|
|
$extension = pathinfo($filename, PATHINFO_EXTENSION);
|
|
$basename = pathinfo($filename, PATHINFO_FILENAME);
|
|
|
|
$asciiBase = Str::ascii($basename);
|
|
$asciiBase = preg_replace('/[^A-Za-z0-9._-]+/', '_', (string) $asciiBase);
|
|
$asciiBase = trim((string) $asciiBase, '._-');
|
|
if ($asciiBase === '') {
|
|
$asciiBase = 'download';
|
|
}
|
|
|
|
$asciiExtension = Str::ascii((string) $extension);
|
|
$asciiExtension = preg_replace('/[^A-Za-z0-9]+/', '', (string) $asciiExtension);
|
|
|
|
return $asciiExtension === ''
|
|
? $asciiBase
|
|
: "{$asciiBase}.{$asciiExtension}";
|
|
}
|
|
|
|
private static function sanitizeHeaderFilename(string $filename): string
|
|
{
|
|
$filename = str_replace(["\r", "\n"], '', trim($filename));
|
|
|
|
return $filename !== '' ? $filename : 'download';
|
|
}
|
|
}
|