Update media-url.php
This commit is contained in:
@@ -127,14 +127,16 @@ if ($download) {
|
|||||||
$headers = ['User-Agent: WhatsAppMediaProxy/1.0', 'Accept: */*'];
|
$headers = ['User-Agent: WhatsAppMediaProxy/1.0', 'Accept: */*'];
|
||||||
if ($token) $headers[] = 'Authorization: Bearer ' . $token;
|
if ($token) $headers[] = 'Authorization: Bearer ' . $token;
|
||||||
|
|
||||||
|
// Pedimos cabeceras + body para poder extraer Content-Disposition
|
||||||
curl_setopt_array($ch, [
|
curl_setopt_array($ch, [
|
||||||
CURLOPT_URL => $mediaUrl,
|
CURLOPT_URL => $mediaUrl,
|
||||||
CURLOPT_RETURNTRANSFER => true,
|
CURLOPT_RETURNTRANSFER => true,
|
||||||
CURLOPT_FOLLOWLOCATION => true,
|
CURLOPT_FOLLOWLOCATION => true,
|
||||||
CURLOPT_TIMEOUT => 60,
|
CURLOPT_TIMEOUT => 60,
|
||||||
CURLOPT_HTTPHEADER => $headers,
|
CURLOPT_HTTPHEADER => $headers,
|
||||||
|
CURLOPT_HEADER => true,
|
||||||
]);
|
]);
|
||||||
$content = curl_exec($ch);
|
$response = curl_exec($ch);
|
||||||
$info = curl_getinfo($ch);
|
$info = curl_getinfo($ch);
|
||||||
$err = curl_error($ch);
|
$err = curl_error($ch);
|
||||||
curl_close($ch);
|
curl_close($ch);
|
||||||
@@ -146,14 +148,85 @@ if ($download) {
|
|||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
// Cabeceras para descarga
|
$headerSize = isset($info['header_size']) ? (int)$info['header_size'] : 0;
|
||||||
|
$headersText = $headerSize ? substr($response, 0, $headerSize) : '';
|
||||||
|
$body = $headerSize ? substr($response, $headerSize) : $response;
|
||||||
|
|
||||||
|
// Parsear cabeceras simples
|
||||||
|
$parsed = [];
|
||||||
|
if ($headersText) {
|
||||||
|
$lines = preg_split('/\r?\n/', $headersText);
|
||||||
|
foreach ($lines as $line) {
|
||||||
|
if (strpos($line, ':') !== false) {
|
||||||
|
list($n, $v) = explode(':', $line, 2);
|
||||||
|
$parsed[strtolower(trim($n))] = trim($v);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
$contentType = $parsed['content-type'] ?? ($info['content_type'] ?? null);
|
||||||
|
|
||||||
|
// Si la respuesta es JSON, retornar el error en JSON (evitar descargar JSON como archivo)
|
||||||
|
if ($contentType && stripos($contentType, 'application/json') !== false) {
|
||||||
|
$decoded = json_decode($body, true);
|
||||||
|
http_response_code($decoded && isset($decoded['error']) ? 502 : 500);
|
||||||
|
header('Content-Type: application/json; charset=utf-8');
|
||||||
|
echo json_encode(['success' => false, 'error' => 'Remote server returned JSON instead of file', 'remote' => $decoded]);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Determinar filename desde Content-Disposition o URL como fallback
|
||||||
|
$filename = null;
|
||||||
|
$cd = $parsed['content-disposition'] ?? null;
|
||||||
|
if ($cd) {
|
||||||
|
if (preg_match('/filename\*=(?:[^']*'')?(.+)$/i', $cd, $m)) {
|
||||||
|
$filename = trim($m[1], " \"'\r\n");
|
||||||
|
$filename = rawurldecode($filename);
|
||||||
|
} elseif (preg_match('/filename="?([^";]+)"?/i', $cd, $m)) {
|
||||||
|
$filename = trim($m[1]);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
if (!$filename) {
|
||||||
|
$path = parse_url($mediaUrl, PHP_URL_PATH) ?: '';
|
||||||
|
$basename = basename($path);
|
||||||
|
if ($basename && $basename !== '/') {
|
||||||
|
$filename = $basename;
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
// Si aún no hay filename, intentar deducir extensión desde content-type
|
||||||
|
if (!$filename) {
|
||||||
|
$ext = '';
|
||||||
|
$mimeMap = [
|
||||||
|
'application/pdf' => '.pdf',
|
||||||
|
'text/csv' => '.csv',
|
||||||
|
'image/jpeg' => '.jpg',
|
||||||
|
'image/png' => '.png',
|
||||||
|
'application/zip' => '.zip',
|
||||||
|
'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet' => '.xlsx',
|
||||||
|
'application/vnd.ms-excel' => '.xls',
|
||||||
|
];
|
||||||
|
if ($contentType && isset($mimeMap[strtolower($contentType)])) {
|
||||||
|
$ext = $mimeMap[strtolower($contentType)];
|
||||||
|
}
|
||||||
|
$filename = 'download' . $ext;
|
||||||
|
}
|
||||||
|
|
||||||
|
if ($body === null || $body === '') {
|
||||||
|
http_response_code(502);
|
||||||
|
header('Content-Type: application/json; charset=utf-8');
|
||||||
|
echo json_encode(['success' => false, 'error' => 'Empty response body from remote']);
|
||||||
|
exit;
|
||||||
|
}
|
||||||
|
|
||||||
|
// Enviar body como descarga
|
||||||
header_remove('Content-Type');
|
header_remove('Content-Type');
|
||||||
header('Cache-Control: public, max-age=3600');
|
header('Cache-Control: public, max-age=3600');
|
||||||
if (!empty($info['content_type'])) header('Content-Type: ' . $info['content_type']);
|
if (!empty($contentType)) header('Content-Type: ' . $contentType);
|
||||||
if (!empty($info['size_download'])) header('Content-Length: ' . $info['size_download']);
|
header('Content-Length: ' . strlen($body));
|
||||||
$filename = basename(parse_url($mediaUrl, PHP_URL_PATH) ?: 'file');
|
|
||||||
header('Content-Disposition: attachment; filename="' . $filename . '"');
|
header('Content-Disposition: attachment; filename="' . $filename . '"');
|
||||||
echo $content;
|
echo $body;
|
||||||
exit;
|
exit;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
Reference in New Issue
Block a user