J'ai besoin d'écrire un fichier CSV sur le tampon de sortie PHP, puis de télécharger ce fichier sur l'ordinateur du client après sa rédaction. (Je voulais simplement l'écrire sur le serveur et le télécharger, ce qui fonctionnait, mais je n'aurai pas accès en écriture sur les serveurs de production).
J'ai le script PHP suivant: P>
$basic_info = fopen("php://output", 'w');
$basic_header = array(HEADER_ITEMS_IN_HERE);
@fputcsv($basic_info, $basic_header);
while($user_row = $get_users_stmt->fetch(PDO::FETCH_ASSOC)) {
@fputcsv($basic_info, $user_row);
}
@fclose($basic_info);
header('Content-Description: File Transfer');
header('Content-Type: application/csv');
header('Content-Disposition: attachment; filename=test.csv');
header('Expires: 0');
header('Cache-Control: must-revalidate');
header('Pragma: public');
header('Content-Length: ' . filesize("php://output"));
ob_clean();
flush();
readfile("php://output");
3 Réponses :
Vous faites un peu trop. Créez le script dans le seul but de sortir le CSV. Il suffit d'imprimer directement à l'écran. Ne vous inquiétez pas des en-têtes ou des tampons ou de la PHP: // la sortie ou quelque chose comme ça.
Une fois que vous avez confirmé que vous imprimez les données à l'écran de manière appropriée, ajoutez simplement ces en-têtes au début: < / p> ... Confirmez que cela télécharge le fichier de manière appropriée. Ensuite, vous pouvez ajouter les autres en-têtes si vous le souhaitez (les en-têtes que j'ai inclus ci-dessus sont ceux que je me suis utilisé sans aucun cruft supplémentaire pour obtenir ce travail, les autres sont essentiellement pour l'efficacité et le contrôle de cache, dont certains peuvent déjà être traités de manière appropriée Par votre serveur, et peut être important ou non pour votre application particulière). P> Si vous le souhaitez, utilisez la mémoire tampon de sortie avec ob_start () code> et ob_get_clean () < / Code> Pour obtenir le contenu de la sortie dans une chaîne que vous pouvez ensuite utiliser pour remplir longueur de contenu code>. p> p>
merci de m'avoir aidé à différer les autres qui se plaingent de choses que je fais mal
J'ai fait des modifications à votre code.
N'oubliez pas que l'en-tête () doit être appelé avant que toute sortie réelle ne soit envoyé, soit par balises HTML normales, lignes vierges dans un fichier ou à partir de PHP P> blockQuote>
- a retiré certains en-têtes qui n'ont pas fait beaucoup de changement; li>
- a commenté une autre option d'écriture de l'en-tête CSV à l'aide des noms de sélection de colonne; LI>
- Maintenant la longueur de contenu fonctionne; li>
- Il n'est pas nécessaire d'echo $ basic_info tel qu'il est déjà au tampon de sortie et nous l'avons redirigé à l'intérieur d'un fichier à travers des en-têtes; Li>
- Supprimé
@ code> (opérateur de contrôle d'erreur PHP) car il peut causer des frais généraux, ne pas avoir de lien pour vous montrer maintenant mais que vous pourriez le trouver si vous recherchez. Vous devriez réfléchir à deux fois avant de faire de la silence des erreurs,la plupart des temps forts> il devrait être fixé au lieu de silence. Li> ul>
xxx pré> p>
Les en-têtes ne sont-ils pas déjà envoyés à l'en-tête («longueur de contenu:». $ Streamsize); Depuis que vous avez écrit à PHP: // sortie avant?
@dnfer Oui mais je ne peux connaître que la taille du fichier après la finition de l'écriture, ce qui fonctionne, le navigateur affiche la taille du fichier à télécharger Pop Up.
Je me rends compte. Mais je me demande une sorte que les "en-têtes déjà envoyés" avertissement ne se présentent pas.
J'avais reçu un message d'erreur "en-têtes déjà envoyé" lors de l'ajout de l'en-tête de longueur de contenu lorsque vous décrivez ci-dessus. Réussi à résoudre ceci en utilisant ob_start () code> avant la sortie CSV et ob_end_flush () code> après l'en-tête de longueur de contenu. En fonction de la fréquence de votre script pour traiter le téléchargement, le téléchargement commencera un peu plus tard que sans utiliser le tampon de sortie car l'ensemble du fichier sera préparé en premier, puis envoyé au client. L'UPSE est que l'utilisateur peut voir la taille du téléchargement et le navigateur peut mieux estimer le temps de téléchargement de téléchargement restant.
Comme mentionné dans mes commentaires de la réponse d'Edson, je m'attendais à un avertissement "en-têtes déjà envoyé" à la dernière ligne de code: puisque la sortie est écrite avant que cet en-tête soit envoyé, mais Son exemple fonctionne bien. P> Certaines enquêtes me conduisent à suivre les conclusions suivantes: P> Au moment où vous utilisez un tampon de sortie (Wei, un utilisateur, ou le
Par défaut PHP One), vous pouvez envoyer des en-têtes HTTP et le contenu de la manière dont vous
vouloir. Vous savez que tout protocole nécessite d'envoyer des en-têtes avant le corps
(Ainsi, le terme "en-tête"), mais lorsque vous utilisez une couche de tampon de sortie, PHP
prendra en charge cela pour vous. Toute fonction PHP jouant avec la sortie
les en-têtes (en-tête (), Setcookie (), Session_Start ()) utilisera en fait la
Fonction interne sapi_header_op () qui se remplit juste dans les en-têtes
amortir. Lorsque vous écrivez la sortie, utilisez Say Printf (), il écrit dans
le tampon de sortie (en supposant un). et p> La taille par défaut du tampon PHP sous la plupart des configurations est 4096
octets (4 ko), ce qui signifie que les tampons PHP peuvent contenir des données jusqu'à 4 Ko. Le code d'Edson fonctionne car le tampon de sortie ne s'est pas produit automatiquement, car il ne dépasse pas la taille de la mémoire tampon (et le script n'est pas terminé évidemment avant l'envoi de la dernière en-tête). P> < P> Dès que les données du tampon de sortie dépassent la taille du tampon, l'avertissement sera soulevé. Ou dans son exemple, lorsque les données de p> sont trop grandes. P> Pour éviter cela, vous devez gérer la mise en mémoire tampon de sortie avec l'OB_START ( ) et ob_end_flush (); Comme ci-dessous: p> Vous êtes toujours lié à d'autres limites, cependant. p> p>
Si vous écrivez sur le tampon de sortie, vous l'envoyez immédiatement au client. Auquel cas les en-têtes doivent être envoyés en premier.
ob_clean () est inutile à moins que vous ayez fait un ob_start () quelque part. Et considérez que ReadFile écrit à la sortie, mais vous lisez à partir de cette entrée. Sauf si vous avez fait un ob_start () avant tout ce code, votre FPTCSV () a écrit à la sortie et est allé sur le navigateur avant que l'un des codes d'en-tête ne soit exécuté.
Je peux nommer littéralement une méthode en PHP chaque fois que l'utilisation de "@" peut être justifiée. Ce n'est pas dans votre code, alors au lieu de planter @ sur chaque ligne, vous pouvez écrire votre code correctement au début?
@Webnetmobile non désériorize ()?
@Webnetmobile My Deveux est
Mail () Code>.@Webnetmobile Je dispose en fait de la manipulation des erreurs dans le code mais je viens de le mettre là parce que je ne voulais pas inclure aucun de ce code
@DataSage pour que je puisse déplacer mes en-têtes avant d'écrire à la sortie. Mes en-têtes sont-ils corrects?
@Marcb Donc, si je déplace mes en-têtes au début, j'ai même besoin d'appels OB_CLEAN (), FUSH () ou LIFFILE ()?
non. Pourquoi tamponner quelque chose que vous allez simplement produire de toute façon? Vous ne produisez rien que les données CSV, la tampon est donc inutile.