PHP - header location vers un lien symbolique, pas de poid sous IE

Bonjour,
Je viens de créer un script pour gérer les téléchargements (compteur + droit d’accès).
Suite à des limitations de mon hébergeur et pour répondre à certaines contraintes, j’ai opté pour les liens symboliques.
Pour résumé (et pour expliquer le principe) :
1 - L’utilisateur demande un fichier
2 - Le script PHP vérifie le droit d’accès à ce fichier + incrémentation du compteur de téléchargement
3 - Le script effectuer une redirection vers le lien symbolique créé pour le téléchargement

Je n’ai aucun problème jusqu’au moment du téléchargement. En effet, le poids du fichier n’est pas envoyé au navigateur Internet Explorer, tandis qu’Opera et Mozilla reçoivent bien le Content-Lenght.
Après vérification à l’aide de Wireshark, l’en-tête concernant le poids du fichier n’est jamais envoyé lorsque j’utilise IE

J’ai essayé de forcer le header Content-Lenght en l’insérant dans mon script ( header('Content-Length: '.filesize($file)); ), mais rien à faire, IE prend bien en compte la redirection, mais n’a jamais l’information du poids du fichier ; ce qui a pour conséquence que le client n’a pas connaissance du pourcentage du téléchargement effectué.

Je pense que le problème vient d’évidement d’Internet Explorer, mais puis-je forcer l’envoie de ce header, et si oui, comment ?

Je vous remercie pour aide :wink:
Edité le 31/08/2010 à 12:40

Tu fais quoi exactement, tu ne fais quand même pas un header(‘Location: …’) ?

Tu fais genre un fpassthru ?

Merci Sans-Nom de ta réponse, mais mon script PHP est une sorte de passerelle pour le téléchargement de fichiers (comme tu l’aura certainement compris), cependant ceux-ci assez volumineux (de quelques Mo à 1Go+).
Je ne peux pas utiliser les fonctions readfile/fopen/fpassthru etc.
Voila pourquoi j’utilise une simple redirection vers un lien symbolique.

Voici le code PHP :


<?php
session_start();

if(!empty($_SESSION['liste_fichiers']) && !empty($_GET['fichier']) && ($_GET['fichier'] !== 'index.php' || $_GET['fichier'] !== '.htaccess')) {

	$fichier=htmlentities($_GET['fichier']);

	if(file_exists("fichiers/".$fichier) && in_array($fichier, $_SESSION['liste_fichiers'])) {

			$ip_client = $_SERVER['REMOTE_ADDR'];
			$hash_session = sha1(session_id());
			$repertoire = 'telechargements/';
			$date = date('Y-m');
			$fichier_xml = 'logs/telechargements_'.$date.'.xml';

			// compteur au niveau du fichier de description
			if(file_exists('fichiers_descriptions/'.$fichier.'.xml')) {
				$xml = simplexml_load_file('fichiers_descriptions/'.$fichier.'.xml');
				$sxe = new SimpleXMLElement($xml->asXML());
				$nb_telechargement = $sxe->nombre_telechargements;
				$sxe->nombre_telechargements = $nb_telechargement + 1;
				$output = $sxe->asXML('fichiers_descriptions/'.$fichier.'.xml');
			}

			// edition/generation du log
			$doc_xml = new DOMDocument('1.0', 'utf-8');

			if(file_exists($fichier_xml)) {
				$doc_xml->preserveWhiteSpace = false;
				$doc_xml->load($fichier_xml);

				$racine = $doc_xml->documentElement;
			} else {
				// racine
				$racine = $doc_xml->appendChild($doc_xml->createElement('telechargements'));

				// attributs de l'element "telechargement"
				$racine_attr = $racine->appendChild($doc_xml->createAttribute('mois'));
				$racine_attr = $racine_attr->appendChild($doc_xml->createTextNode(date('m')));

				$racine_attr = $racine->appendChild($doc_xml->createAttribute('annee'));
				$racine_attr = $racine_attr->appendChild($doc_xml->createTextNode(date('Y')));
			}

			// noeud "date"
			$date = $racine->appendChild($doc_xml->createElement('date'));

			// attributs de l'element "date"
			$date_attr = $date->appendChild($doc_xml->createAttribute('date'));
			$date_attr = $date_attr->appendChild($doc_xml->createTextNode(date('d-m-Y')));

			$date_attr = $date->appendChild($doc_xml->createAttribute('horaire'));
			$date_attr = $date_attr->appendChild($doc_xml->createTextNode(date('H:i:s')));

			// elements du noeud
			$date_child = $date->appendChild($doc_xml->createElement('utilisateur', $_SESSION['utilisateur']));
			$date_child = $date->appendChild($doc_xml->createElement('adresse_ip', $ip_client));
			$date_child = $date->appendChild($doc_xml->createElement('fichier', $fichier));

			$doc_xml->formatOutput = true; 
			$doc_xml->normalizeDocument();
			$doc_xml->save($fichier_xml);


			// preparation au téléchargement

			// création du repertoire de session si il n'existe pas
			if(!file_exists($repertoire.$hash_session)) {
				mkdir($repertoire.$hash_session);
			}

			// création du .htaccess :)
			if(!file_exists($repertoire.$hash_session.'/.htaccess')) {
				$htaccess = "#Utilisateur : ".$_SESSION['utilisateur']."\nOptions -Indexes\ndeny from all\nallow from ".$_SERVER['REMOTE_ADDR'];
				file_put_contents($repertoire.$hash_session.'/.htaccess', $htaccess);
			}

			$target = '../../fichiers/'.$fichier;
			$link = $repertoire.$hash_session.'/'.$fichier;

			// téléchargement du fichier (création du lien symbolique)
			if(@symlink($target, $link) || is_link($link)) {
				header('Location: ../'.$link);
				exit;
			} else {
				//une erreur s'est produite, l'administrateur est prévenu :o
				echo 'erreur ...';
				exit;
			}

	} else {
		//erreur 404;
		header("HTTP/1.1 404 Not Found");
		header("Status: 404 Not Found");
		exit;
	}
} else {
	//erreur 404;
	header("HTTP/1.1 404 Not Found");
	header("Status: 404 Not Found");
	exit;
}

?>

Alors non, je pense qu’IE a un comportement plus ou moins normal. Si tu fournis une taille, et une redirection HTTP, le navigateur va relancer la requête sur cette url, c’est donc logique qu’il ignore la taille d’avant. Ce qui est bizarre, c’est que ton serveur web ne lui fournisse pas, parce que du coup c’est Apache qui lui fournit le fichier -> il doit le mettre dans l’entête.

Tu as essayer d’ouvrir le fichier directement (après avoir créer le lien symbolique) dans IE voir ce qu’il faisait ?

Sinon essaye plutôt d’ouvrir et d’afficher le fichier sur la sortie standard - après l’avoir écrit - en utilisant fpassthru

Cela ne devrait pas poser trop de problème de lenteur pour php, vu que ce n’est que de la redirection de sortie

Sinon, dans Location, l’url doit être absolue (= chemin depuis la racine de ton serveur). Cela n’est peut-être pas le problème.

Merci encore pour ton aide.

Concernant fpassthu, j’avais évidemment essayé, cela revient à utiliser fopen et tout ce qui va avec. Voici par exemple un message d’erreur obtenue lors de lecture de fichiers volumineux avec ce type de fonction :
Fatal error: Allowed memory size of 134217728 bytes exhausted

Cette erreur est inhérente à Wamp et à mon hébergeur (hébergement mutualisé)

Concernant le problème originel et le fait que j’utilise les liens symboliques : forum.ovh.com… :wink:

J’avais évidemment testé en lien direct (sans passer par le header(Location: …)), mais en copiant collant l’URL dans IE, sans grand résultat :confused:

Concernant le fait d’utiliser le chemin absolu, c’est rectifié, merci :wink:

Edit : je viens de trouver l’origine du problème. A la racine de mon site, j’ai activer le mode Deflate (gzip), ça fait merder les en-têtes


AddOutputFilterByType DEFLATE text/plain
AddOutputFilterByType DEFLATE text/xml
AddOutputFilterByType DEFLATE text/html
AddOutputFilterByType DEFLATE text/css
AddOutputFilterByType DEFLATE image/svg+xml
AddOutputFilterByType DEFLATE application/xhtml+xml
AddOutputFilterByType DEFLATE application/xml
AddOutputFilterByType DEFLATE application/rss+xml
AddOutputFilterByType DEFLATE application/atom_xml
AddOutputFilterByType DEFLATE application/x-javascript
AddOutputFilterByType DEFLATE application/x-httpd-php
AddOutputFilterByType DEFLATE application/x-httpd-fastphp
AddOutputFilterByType DEFLATE application/x-httpd-eruby
SetOutputFilter DEFLATE
SetEnvIfNoCase Request_URI \.(?:gif|jpeg|png)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.(?:exe|tgz|zip|bz2|sit|rar)$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.pdf$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.avi$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.mov$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.mp3$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.mp4$ no-gzip dont-vary
SetEnvIfNoCase Request_URI \.rm$ no-gzip dont-vary

Je n’ai plus qu’à trouver quelle ligne fait merder.

Merci encore pour ton aide Sans-Nom (pas hadopi hein ^^)

Je mettrai la réponse ici :wink:

Edit bis : le problème vient de la ligne SetOutputFilter DEFLATE, des que j’active le filtre, ça merde (même sans les directives du filtres ^^).

Edit ter : Le problème vient en fait de là :


BrowserMatch \bMSIE !no-gzip !gzip-only-text/html
BrowserMatch \bMSI[E] !no-gzip !gzip-only-text/html

Il faut que je commente les deux fichier et j’ai le poids de mon archive, je ne sais pas comment est-ce que je vais gérer ça encore (je laisse commenté pour l’instant), mais si vous avez des idées :wink:
Edité le 31/08/2010 à 12:30

Après avoir installé le logiciel ieHTTPHeaders et pu vérifier que le mode Deflate était activé, j’ai décidé de laisser commenter les lignes énoncées ci-dessus.

Si vous ne pensez pas que c’est une excellente idée, dites-le-moi, mais bon, ça a résolu mon problème :slight_smile:

Merci encore de ton aide Sans-Nom :wink:
Edité le 31/08/2010 à 12:39