PHP et d'autres scripts côté serveur fournissent la fonction de téléchargement de fichiers, et elle est relativement simple à mettre en œuvre. En utilisant JavaScript pour coopérer, vous pouvez implémenter le téléchargement de fichiers Ajax. Bien que jQuery lui-même ne fournisse pas une fonction aussi simplifiée, il existe de nombreux plug-ins qui peuvent y parvenir. Parmi eux, ajaxfileupload.js fourni par Phpletter.com est un plug-in léger, et sa méthode d'écriture est très similaire à la méthode globale $.post() fournie par jQuery, qui est simple et facile à utiliser.
Cependant, le plug-in est trop simplifié. En plus de fournir le chemin du fichier à télécharger, il ne peut pas transmettre de valeurs supplémentaires au serveur backend. J'ai donc modifié le script et ajouté un paramètre d'objet de données.
1.Principe
J'utilise PHP comme script serveur ici. Presque tous les livres sans PHP mentionneront comment utiliser la méthode move_uploaded_file() pour télécharger des fichiers, je n'entrerai donc pas dans les détails ici. Ce que je veux dire, c'est d'utiliser le principe du téléchargement Ajax.
Parce que j'utilise la bibliothèque jQuery, quand je pense à Ajax, ma première réaction est d'essayer la méthode $.post(), d'utiliser chaque sélecteur pour obtenir la valeur dans la zone fichier, puis de la soumettre au serveur d'arrière-plan. . Bien sûr, il s’est avéré plus tard que cela ne fonctionnait pas. (En raison de ce problème, j'ai également vérifié beaucoup d'informations, et il existe de nombreux scripts ASP et autres disponibles en ligne. Je ne sais vraiment pas quoi dire.)
Pour revenir au sujet, il n'est pas difficile d'implémenter le téléchargement Ajax et il existe de nombreuses méthodes. Le plug-in ajaxfileupload.js de Phpletter.com mentionné dans cet article utilise iframe. Il s'agit également d'une méthode courante pour réaliser le téléchargement sans actualiser la page lorsque vous n'utilisez pas de scripts JavaScript. (Ce blog utilise cette méthode pour écrire des logs en arrière-plan de bo-blog)
Le plug-in ajaxfileupload.js est également très simple. Il utilise d'abord le sélecteur de jQuery pour obtenir la valeur du chemin du fichier dans la boîte de téléchargement du fichier, puis crée dynamiquement une iframe et y crée une nouvelle boîte de fichier, fournissant une méthode de publication pour soumettre. dans les coulisses. Enfin, les résultats sont renvoyés à la réception.
2. Utiliser
L'utilisation du plug-in ajaxfileupload.js est très simple.
Le code HTML du frontend est similaire :
<script type="text/javascript"> $(#buttonUplod).click(function () { $.ajaxFileUpload ({ url:'doajaxfileupload.php', //你处理上传文件的服务端 secureuri:false, //与页面处理代码中file相对应的ID值 fileElementId:'img', dataType: 'json', //返回数据类型:text,xml,json,html,scritp,jsonp五种 success: function (data) { alert(data.file_infor); } }) }); </script> <input id="img" type="file" size="45" name="img" > <button id="buttonUpload" onclick="return ajaxFileUpload();">Upload</button>
Script backend doajaxfileupload.php :
<?php $upFilePath = "../attachment/"; $ok=@move_uploaded_file($_FILES['img']['tmp_name'],$upFilePath); if($ok === FALSE){ echo json_encode('file_infor'=>'上传失败'); }else{ echo json_encode('file_infor'=>'上传成功'); } ?>
Pour les tests, vous pouvez enregistrer la valeur de la variable transmise en utilisant une méthode similaire à la suivante :
$file_info = var_export($_FILES,true);
$ok = file_put_contents("../attachment/file_info.txt",$file_info);
if ($ok) exit(json_encode('file_infor'=>'Téléchargement réussi'));
exit (json_encode('file_infor'=>'Échec du téléchargement'));
※ Remarque
Veuillez noter la balise dans la zone du fichier de code HTML :
1. id='img' est utilisé pour identifier le fileElementId:'img' du plug-in ajaxfileupload.js Le sélecteur jQuery utilisera cette chaîne pour obtenir la valeur de la zone de texte
.
2. name='img' est utilisé lors de la soumission au script d'arrière-plan via le mode post. PHP lit les données du fichier téléchargé via $_FILES['img']. S'il n'y a pas une telle valeur, la variable $_FILES est vide ;
Donc, ces deux valeurs sont indispensables et ne peuvent être confondues.
3. Prise en charge de paramètres supplémentaires
Parfois, nous devons traiter les fichiers téléchargés en fonction de certaines variables en arrière-plan. Par exemple, mettez à jour les fichiers. À ce stade, vous devez transmettre certains paramètres supplémentaires à la même étape. J'ai donc modifié le plugin ajaxfileupload.js :
addOtherRequestsToForm: function(form,data) { // add extra parameter var originalElement = $('<input type="hidden" name="" value="">'); for (var key in data) { name = key; value = data[key]; var cloneElement = originalElement.clone(); cloneElement.attr({'name':name,'value':value}); $(cloneElement).appendTo(form); } return form; }, ajaxFileUpload: function(s) { // TODO introduce global settings, allowing the client to modify them for all requests, not only timeout s = jQuery.extend({}, jQuery.ajaxSettings, s); var id = new Date().getTime() var form = jQuery.createUploadForm(id, s.fileElementId); if ( s.data ) form = jQuery.addOtherRequestsToForm(form,s.data); var io = jQuery.createUploadIframe(id, s.secureuri);
La partie marquée en rouge est le contenu que j'ai ajouté. De cette façon, je peux transmettre des paramètres supplémentaires dans la partie HTML frontend via un code similaire au suivant :
url:'doajaxfileupload.php', //Votre serveur qui gère les fichiers téléchargés
secureuri:false, //valeur ID correspondant au fichier dans le code de traitement de la page
data:{'test':'test','ok':'ok'}, //Transmises en tant qu'objet, les valeurs des variables JavaScript peuvent être saisies dans la partie contenu
fileElementId : 'img',
Le script de traitement en arrière-plan est :
array_push($_FILES,$_REQUEST); $file_info = var_export($_FILES,true); $ok = file_put_contents("../attachment/file_info.txt",$file_info); if ($ok) exit(json_encode('file_infor'=>'上传成功')); exit (json_encode('file_infor'=>'上传失败'));
On voit que le principe est très simple, c'est-à-dire ajouter le contenu supplémentaire de l'objet de données au formulaire sous l'iframe, le transmettre au script PHP d'arrière-plan, et obtenir ces valeursavec des variables telles que $_REQUEST.
Le contenu de file_info.txt retenu dans la sortie en arrière-plan est le suivant :
tableau (
'fichier' =>
tableau (
'name' => 'firefox-java.txt',
'type' => 'texte/plain',
'tmp_name' => 'D:\Tools\xampp\tmp\phpED45.tmp',
'erreur' => 0,
'taille' => 250,
),
0 =>
tableau (
'test' => 'test',
'ok' => 'ok',
'PHPSESSID' => 'e379fd4fb2abca6e802a1302805a5535',
),
)
ajaxfileupload.js :
jQuery.extend({ createUploadIframe: function(id, uri) { //create frame var frameId = 'jUploadFrame' + id; if(window.ActiveXObject) { var io = document.createElement('<iframe id="' + frameId + '" name="' + frameId + '" />'); if(typeof uri== 'boolean'){ io.src = 'javascript:false'; } else if(typeof uri== 'string'){ io.src = uri; } } else { var io = document.createElement('iframe'); io.id = frameId; io.name = frameId; } io.style.position = 'absolute'; io.style.top = '-1000px'; io.style.left = '-1000px'; document.body.appendChild(io); return io }, createUploadForm: function(id, fileElementId) { //create form var formId = 'jUploadForm' + id; var fileId = 'jUploadFile' + id; var form = $('<form action="" method="POST" name="' + formId + '" id="' + formId + '" enctype="multipart/form-data"></form>'); var oldElement = $('#' + fileElementId); var newElement = $(oldElement).clone(); $(oldElement).attr('id', fileId); $(oldElement).before(newElement); $(oldElement).appendTo(form); //set attributes $(form).css('position', 'absolute'); $(form).css('top', '-1200px'); $(form).css('left', '-1200px'); $(form).appendTo('body'); return form; }, addOtherRequestsToForm: function(form,data) { // add extra parameter var originalElement = $('<input type="hidden" name="" value="">'); for (var key in data) { name = key; value = data[key]; var cloneElement = originalElement.clone(); cloneElement.attr({'name':name,'value':value}); $(cloneElement).appendTo(form); } return form; }, ajaxFileUpload: function(s) { // TODO introduce global settings, allowing the client to modify them for all requests, not only timeout s = jQuery.extend({}, jQuery.ajaxSettings, s); var id = new Date().getTime() var form = jQuery.createUploadForm(id, s.fileElementId); if ( s.data ) form = jQuery.addOtherRequestsToForm(form,s.data); var io = jQuery.createUploadIframe(id, s.secureuri); var frameId = 'jUploadFrame' + id; var formId = 'jUploadForm' + id; // Watch for a new set of requests if ( s.global && ! jQuery.active++ ) { jQuery.event.trigger( "ajaxStart" ); } var requestDone = false; // Create the request object var xml = {} if ( s.global ) jQuery.event.trigger("ajaxSend", [xml, s]); // Wait for a response to come back var uploadCallback = function(isTimeout) { var io = document.getElementById(frameId); try { if(io.contentWindow) { xml.responseText = io.contentWindow.document.body?io.contentWindow.document.body.innerHTML:null; xml.responseXML = io.contentWindow.document.XMLDocument?io.contentWindow.document.XMLDocument:io.contentWindow.document; }else if(io.contentDocument) { xml.responseText = io.contentDocument.document.body?io.contentDocument.document.body.innerHTML:null; xml.responseXML = io.contentDocument.document.XMLDocument?io.contentDocument.document.XMLDocument:io.contentDocument.document; } }catch(e) { jQuery.handleError(s, xml, null, e); } if ( xml || isTimeout == "timeout") { requestDone = true; var status; try { status = isTimeout != "timeout" ? "success" : "error"; // Make sure that the request was successful or notmodified if ( status != "error" ) { // process the data (runs the xml through httpData regardless of callback) var data = jQuery.uploadHttpData( xml, s.dataType ); // If a local callback was specified, fire it and pass it the data if ( s.success ) s.success( data, status ); // Fire the global callback if( s.global ) jQuery.event.trigger( "ajaxSuccess", [xml, s] ); } else jQuery.handleError(s, xml, status); } catch(e) { status = "error"; jQuery.handleError(s, xml, status, e); } // The request was completed if( s.global ) jQuery.event.trigger( "ajaxComplete", [xml, s] ); // Handle the global AJAX counter if ( s.global && ! --jQuery.active ) jQuery.event.trigger( "ajaxStop" ); // Process result if ( s.complete ) s.complete(xml, status); jQuery(io).unbind() setTimeout(function() { try { $(io).remove(); $(form).remove(); } catch(e) { jQuery.handleError(s, xml, null, e); } }, 100) xml = null } } // Timeout checker if ( s.timeout > 0 ) { setTimeout(function(){ // Check to see if the request is still happening if( !requestDone ) uploadCallback( "timeout" ); }, s.timeout); } try { // var io = $('#' + frameId); var form = $('#' + formId); $(form).attr('action', s.url); $(form).attr('method', 'POST'); $(form).attr('target', frameId); if(form.encoding) { form.encoding = 'multipart/form-data'; } else { form.enctype = 'multipart/form-data'; } $(form).submit(); } catch(e) { jQuery.handleError(s, xml, null, e); } if(window.attachEvent){ document.getElementById(frameId).attachEvent('onload', uploadCallback); } else{ document.getElementById(frameId).addEventListener('load', uploadCallback, false); } return {abort: function () {}}; }, uploadHttpData: function( r, type ) { var data = !type; data = type == "xml" || data ? r.responseXML : r.responseText; // If the type is "script", eval it in global context if ( type == "script" ) jQuery.globalEval( data ); // Get the JavaScript object, if JSON is used. if ( type == "json" ) eval( "data = " + data ); // evaluate scripts within html if ( type == "html" ) jQuery("<div>").html(data).evalScripts(); //alert($('param', data).each(function(){alert($(this).attr('value'));})); return data; } })