Upload de fichier avec barre de progression utilisant Jquery et PHP !

MISE A JOUR IMPORTANTE (15/04/2015): Vous trouverez un script bien plus simple ici : Jquery upload avec barre de progression en HTML5 et php

Salut tout le monde !

Aujourd’hui nous allons voir comment créer notre barre de progression pendant l’envoi d’un fichier ! Il me semble que c’est l’un des scripts les plus demande dans le domaine, alors voila la solution:

Étape 1: Ce qu’il vous faut
PHP >= 5.4

  • Chez OVH, dans votre fichier .htaccess, écrivez SetEnv PHP_VER 5_4 si vous n’êtes pas a jour (attention aux fonction obsolètes tel que mysql_connect(); )

Jquery
Jquery ui (Option)
session.upload_progress.enabled On. Pour vérifier ça, regardez votre phpinfo(); ou trouvez cette ligne dans votre fichier php.ini

Étape 2:  Le formulaire

Créez votre fichier index.php

<form id="myForm" action="" enctype="multipart/form-data" method="POST" name="" target="hidden_iframe">" /&gt; <label for="userfile">Choose a file:</label> <input id="userfile" name="userfile" required="" type="file" /> <input class="ui-corner-all" type="submit" value="Start Upload" /></form>
Étape3: L’iframe
Étant donne qu’il est impossible de traiter des fichiers via ajax, nous allons tout simplement utiliser une astuce pour « simuler » l’asynchrone en inserant et en cachant une iframe contenant le traitement du fichier. Le formulaire doit avoir comme action, l’iframe ! Simple non?
<iframe id="hidden_iframe" src="about:blank" name="hidden_iframe" width="300" height="150"></iframe>
Étape 4: Le traitement du fichier
Créer le fichier upload_frame.php
Ici nous traiterons donc l’envoi du fichier (pas la copie !) et afficherons la progression actuelle.
Étape 5: La barre de progression
Utilisant CSS3, une barre qu’elle est belle ! Créez le fichier progressbar.css

Et dans le fichier progressbar.css

.bar_content { display:inline-block; }
 
.progress-bar {
	background-color: #1a1a1a;
	height: 25px;
	padding: 5px;
	width: 90%;
	min-width:250px;
	overflow:hidden;
	 margin: 20px auto;		
	-moz-border-radius: 5px;
	-webkit-border-radius: 5px;
	border-radius: 5px;
	-moz-box-shadow: 0 1px 5px #000 inset, 0 1px 0 #444;
	-webkit-box-shadow: 0 1px 5px #000 inset, 0 1px 0 #444;
	box-shadow: 0 1px 5px #000 inset, 0 1px 0 #444;           
}
 
.progress-bar span {
	float:left;
	display: inline-block;
	height: 100%;
	background-color: #777;
	-moz-border-radius: 3px;
	-webkit-border-radius: 3px;
	border-radius: 3px;
	-moz-box-shadow: 0 1px 0 rgba(255, 255, 255, .5) inset;
	-webkit-box-shadow: 0 1px 0 rgba(255, 255, 255, .5) inset;
	box-shadow: 0 1px 0 rgba(255, 255, 255, .5) inset;
	-webkit-transition: width .4s ease-in-out;
	-moz-transition: width 1.4s ease-in-out;
	-ms-transition: width 1.4s ease-in-out;
	-o-transition: width 1.4s ease-in-out;
	transition: width 1.4s ease-in-out;		
 
}
 
/*----------- The color of the progress bar ----------------*/			
 
 
.blue span { background-color: #34e359;  }
 
 
/*----------- The stripes (for any browser) ----------------*/		
 
.stripes span {
	-webkit-background-size: 30px 30px;
	-moz-background-size: 30px 30px;
	background-size: 30px 30px;			
	background-image: -webkit-gradient(linear, left top, right bottom,
						color-stop(.25, rgba(255, 255, 255, .15)), color-stop(.25, transparent),
						color-stop(.5, transparent), color-stop(.5, rgba(255, 255, 255, .15)),
						color-stop(.75, rgba(255, 255, 255, .15)), color-stop(.75, transparent),
						to(transparent));
	background-image: -webkit-linear-gradient(135deg, rgba(255, 255, 255, .15) 25%, transparent 25%,
						transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%,
						transparent 75%, transparent);
	background-image: -moz-linear-gradient(135deg, rgba(255, 255, 255, .15) 25%, transparent 25%,
						transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%,
						transparent 75%, transparent);
	background-image: -ms-linear-gradient(135deg, rgba(255, 255, 255, .15) 25%, transparent 25%,
						transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%,
						transparent 75%, transparent);
	background-image: -o-linear-gradient(135deg, rgba(255, 255, 255, .15) 25%, transparent 25%,
						transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%,
						transparent 75%, transparent);
	background-image: linear-gradient(135deg, rgba(255, 255, 255, .15) 25%, transparent 25%,
						transparent 50%, rgba(255, 255, 255, .15) 50%, rgba(255, 255, 255, .15) 75%,
						transparent 75%, transparent);            
 
	-webkit-animation: animate-stripes 3s linear infinite;
	-moz-animation: animate-stripes 3s linear infinite;       		
}
 
@-webkit-keyframes animate-stripes {
	0% {background-position: 0 0;} 100% {background-position: 60px 0;}
}
 
@-moz-keyframes animate-stripes {
	0% {background-position: 0 0;} 100% {background-position: 60px 0;}
}
 
/*---------------------------*/
Étape 6: Copie du fichier uploadé

Dans le fichier index.php

Étape 7: Le script

Dans index.php

<script>// <![CDATA[
$(document).ready(function(){
// The action before and after upload
function toggleBarVisibility() {
$("#status").show("blind", 1000).html('Uploading...');
$( "#bar_blank" ).css( "display", "block");
$(".bar_content").css('width','0%');
}
// We get the current % on upload_frame.php
function sendRequest() {
$.get('upload_frame.php', function(http) { handleResponse(http); });
}
 
//the function for update the progress bar and check if finish
function handleResponse(http) {
//we set the width with jquery
$(".bar_content").css('width',''+http+'%');
// If still not finish, we refresh the request which get the content of upload_frame.php
if (http < 100) { var t=setTimeout(sendRequest, 1000); } // If finish, everything here will be done else { //random effect, do what ever you want $(".bar_content").removeClass(".bar_content").css('width','100%'); $( "#bar_blank" ).delay(2000).hide("highlight", 1000); $("#status").html('Upload finished !').delay(2000).hide("blind", 1000); } } // The function when you send the Form function startUpload() { toggleBarVisibility(); var t=setTimeout(sendRequest, 1000); } //everything start here $("#myForm").submit(function() { if($('#userfile').val() != '') { startUpload(); } }); //just stylish button from jquery ui $( "[type=submit]" ).button(); });
// ]]></script>

DEMO

Pour télécharger le script complet, vous pouvez aller sur mon github. Télécharger.
Il contient une meilleure mise en page, des effets avec jquery ui etc…

N’hesitez pas à poser vos questions, commentez, partager !

Commentaires (8)

  1. david

    Bonjour
    Superbe travail !
    j’essai d’intégrer ton script sur mon site, une question comment faire pour avoir une redirection sur une autre page?
    j’ai essayé header Location … mais impossible car je reste sur la page index
    j’ai modifié ceci :

    et après l’insertion dans ma BD j’ai fais ceci:
    $req = $bdd->prepare(‘INSERT INTO upload(email, date, photo) VALUES(:email, current_timestamp, :photo)’); /* requete pour inserer l’image dans la base de données table upload */
    $req->execute(array(
    ’email’=>$email,
    ‘photo’=>$nom_image1
    )); /* requete preparer */

    if($req)
    {
    $success = header(« location:../upload/upload2.php ») ;
    }
    else
    {
    echo(« L’insertion à échouée ») ;
    }
    }
    }

    je tiens à préciser qu’avant d’intégrer ton script ma redirection fonctionnait, je ne vois vraiment pas ou cela coince
    merci pour ton aide

    Répondre
    1. orugari (Auteur de l'article)

      Bonjour,

      A la place de « Upload Finished! » place ta redirection web en javascript, cela devrait faire l’affaire!

      Répondre
  2. Cédric

    Bonjour,
    dans le cas, où il y a plusieurs fichiers à charger, comment faire pour que la barre de chargement dure le temps de tout le chargement?
    J’ai repris le formulaire pour avoir 5 fichiers, mais je ne sais pas comment faire pour que la barre reste tout le temps du téléchagement. A mon avis, elle ne reste que le temps de l’upload du premier fichier

    Répondre
    1. orugari (Auteur de l'article)

      Je pense qu’il est impossible de garder la même barre de transfert, par contre, tu peux insérer un foreach dans le script qui traiterai tous les fichiers

      Répondre
  3. Sauveur CONSALVI

    Bonjour,
    Votre Upload avec barre de progression est une merveille
    Je ne suis pas un « grand » du PHP
    J’ai quelques notions
    J’ai voulu mettre une limite pour la taille du fichier à Uploader
    J’ai donc saisie :

    <form action=" » method= »POST » id= »myForm » enctype= »multipart/form-data » target= »hidden_iframe »>
    <input type="hidden" value="myForm" name=" » />
    Sélectionner une photo

    ATTENTION : pas plus de 500 Mo

    Là, malheureusement, il y a un os !
    Si le fichier est de taille supérieure à la limite, il n’est pas téléchargé, mais aucun message d’erreur !

    Où peut-on mettre les contrôles pour la sélection du fichier ?
    En plus de la taille, on peut vouloir aussi filtrer des types. (XLS, JPG, …)

    J’ai par exemple des contrôles qui fonctionnes sur un Upload standard

    $file_name = $_FILES[« userfile »][‘name’]; //real file name
    $FichierSize= »{$_FILES[« userfile »][‘size’]} »;
    $Fichiertmpname= »{$_FILES[« userfile »][« tmp_name »]} »;
    $Err= »{$_FILES[« userfile »][« error »]} »;

    echo « Erreur $Err Nom: $file_name Taille: $FichierSize tmpname: $Fichiertmpname « ; // *************************************
    switch ($Err) {
    case 0: // Pas d’erreur
    echo »Pas d\’erreur, fichier copié ! »;
    $chemin_destination = « ./ »;
    $OK=move_uploaded_file(($_FILES[‘userfile’][‘tmp_name’]), $chemin_destination. »NomFic »);
    if ($OK==false) {
    echo »Le fichier n’a put être copié ! « ;
    }
    break;
    case 1: // UPLOAD_ERR_INI_SIZE
    echo »Le fichier dépasse la limite autorisée par le serveur (fichier php.ini) ! »;
    break;
    case 2: // UPLOAD_ERR_FORM_SIZE
    echo « Le fichier dépasse la limite autorisée dans le formulaire HTML ! »;
    break;
    case 3: // UPLOAD_ERR_PARTIAL
    echo « L’envoi du fichier a été interrompu pendant le transfert ! »;
    break;
    case 4: // UPLOAD_ERR_NO_FILE
    echo « Le fichier que vous avez envoyé a une taille nulle ! »;
    break;
    if ($file_name != «  ») {
    if ($FichierSize == 0) {
    echo »Le fichier $FichierNom est trop gros pour être téléchargé. Désolé, mais refaire avec un fichier plus petit … Utilisez la flèche en haut à gauche »;
    exit;
    }
    }

    Où peut-on les placer ?
    Merci d’avance, même si vous ne répondez pas !
    Sauveur CONSALVI

    Répondre
    1. orugari (Auteur de l'article)

      Salut !
      Désolé de cette réponse suuuuper tardive…. malheureusement il n’y a pas de moyen d’empêcher l’upload apres vérification en utilisant cette manière.
      Ce n’est pas encore vraiment au point je trouve ! (l’utilisation de l’iframe c’est un peu tricky)
      Donc a la limite, je te conseille de te rediriger vers uploadify… Ce n’est pas autant modifiable que du pur custom, mais au moins tu peux vérifier les fichiers…

      Répondre
    2. Hatchibu

      if(!empty($_FILES[‘name’][‘tmp_name’]) && is_uploaded_file($_FILES[‘name’][‘tmp_name’])){
      if(filesize($_FILES[‘name’][‘tmp_name’]) voir fonction getimagesize(image_type_to_mime_type) */){
      $monfichier=’monfichier_’.date(« Y\-m\-d\-His »).’.jpg’;
      if(move_uploaded_file($_FILES[‘name’][‘tmp_name’], $monfichier)){
      if(is_file($monfichier)){
      echo ‘Ok’;
      }else echo ‘Erreur avec le chargement du fichier’;
      }else echo ‘Erreur avec le chargement du fichier’;
      }else echo ‘Le fichier doit être de type jpeg’;
      }else echo ‘La taille du fichier doit être inférieur à 5 Mo’;
      }else echo ‘Merci de sélectionner un fichier’;

      Répondre
      1. Hatchibu

        Manque une partie :
        if(filesize($_FILES[‘cartepro’][‘tmp_name’])<5242880){
        list($largeur, $hauteur, $type, $attr)=getimagesize($_FILES['cartepro']['tmp_name']);
        if($type===2){
        $piecejointe='pro/cartepros/carte-pro_test_'.date("Y\-m\-d\-His").'.jpg';

        Répondre

Laisser un commentaire

Votre adresse de messagerie ne sera pas publiée. Les champs obligatoires sont indiqués avec *

h1rB

Please type the text above: