Un avant et interaction face arrière (ajax objets FormData et télécharger des fichiers)

1. Points clés saisir et connaissances

## clé principale

  1. Comprendre ajax utilisation de base
  2. Nous utiliserons l'objet XMLHttpRequest met en œuvre l'échange de données
  3. En savoir onreadystatechange informations de réponse du serveur (code d'état)
  4. Les objets seront utilisés pour télécharger des fichiers FormData
  5. Apprendre le téléchargement objet événement (l'objet événement sous XMLHttpRequest)

## points de connaissances

  1. en utilisant ajax
  2. objet XMLHttpRequest
  3. objets formData
  4. télécharger objet événement

2. Connectez-vous bref rappel

1, proposé ajax vérifier les besoins de nom d'utilisateur;

2, après les erreurs de validation, si résolu en sautant beaucoup d'ennuis;
 

3. Utilisez ajax pour résoudre le problème de la vérification du nom d'utilisateur

- ajax est: Ajax savoir "Asynchronous Javascript And XML" (Asynchronous JavaScript and XML)

- ajax utilisation de base:

  • Nouvel objet XMLHttpRequest;
 let xhr = new XMLHttpRequest();
  • demande de configuration des paramètres
 xhr.open("get","/checkUser",true); //true是异步,false是同步
  • Réception d'une valeur de retour
  xhr.onload = function(){
     let res = JSON.parse(xhr.responseText);
  }
  • Envoi d'une demande de serveur
xhr.send();

Cas est atteint par ajax asynchrone sans actualisation de vérification Nom d'utilisateur:

 login.css:

.loginContainer{
    margin: 0 auto;
    width: 600px;
    text-align: center;
    padding-top: 20px;
    padding-bottom: 50px;
    border: 1px solid;
}
.loginContainer input{
    margin-bottom: 20px;
}
.loginStyle{
    width: 160px;
    height: 40px;
    background: rgb(50,203,77);
    color: white;
    font-size: 17px;
}
.inputStyle{
    width: 200px;
    height: 30px;
    padding: 5px;
    outline: none;
}

.inputStyle:focus{
    border: 1px solid rgb(50,203,77);
}
form{
    position: relative;
}
.exchange{
    position: absolute;
    top:8px;
    right: 65px;
    color: red;
    display: none;
}

user.json:

[
    {
        "id":1,
        "username":"zhangsan",
        "pwd":"123"
    },{
        "id":2,
        "username":"lisi",
        "pwd":"123"
    }
]

 login.js:

const Koa = require("koa");
const Router = require("koa-router");
const static = require("koa-static");
// const views = require("koa-views");
const userData = require("./data/user.json");

let app = new Koa();
let router = new Router();

app.use(static(__dirname + "/static"));
//前面页面直接放到static里时,只能通过login.html访问,不能通过/直接访问
router.get("/checkUser", (cxt, next) => {
    let username = userData.find(item=>item.username === cxt.query.username);
    console.log(username);
    if(username){
        cxt.body = {
            status:1,
            msg:"用户名正确"
        };
    }else{
        cxt.body = {
            status:0,
            msg:"用户名错误"
        };
    }
});

app.use(router.routes());
app.listen("9090");

login.html:

<!DOCTYPE html>
<html lang="en">

<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <meta http-equiv="X-UA-Compatible" content="ie=edge" />
  <link rel="stylesheet" href="css/login.css" />
  <title>Document</title>
</head>

<body>
  <div class="loginContainer">
    <h1>登录</h1>
    <form action="/checkUser" method="post">姓名:
      <input class="inputStyle" type="text" name="username" />
      <div class="exchange">用户名错误</div>
      <br />密码:
      <input class="inputStyle" type="password" name="pwd" /><br />
      <input class="loginStyle" type="submit" value="登录" />
    </form>
  </div>
  <script>
{
  //鼠标失去焦点时,进行无刷新验证
  let username = document.querySelectorAll("input");
  let exchange = document.querySelector(".exchange");
  username[0].onblur = function(){
    let xhr = new XMLHttpRequest();
    xhr.open("get","/checkUser?username="+this.value,true);//true表示异步发送请求,false同步发送请求
    xhr.onload = function() {
      //注意返回数据是从XMLHttpRequest对象中获得的
      let res = JSON.parse(xhr.responseText);
      // console.log(JSON.parse(xhr.responseText).msg);
      // console.log(xhr.response);
      exchange.style.display = "block";
      exchange.innerHTML = JSON.parse(xhr.responseText).msg;
      console.log(res.status);
      
      if(res.status === 1){
        //获取到的数据是JSON格式的,需要将其转为对象
        exchange.style.color = "green";
      }else{
        exchange.style.color = "red";
      }
    }
    xhr.send();
  }
}
  </script>
</body>

4. Pour une explication détaillée de la ajax

Précautions 4.1get

  - paramètre get passant par Parmas

  - obtenir et problèmes queryString par url de participation de masse

obtenir le passage de paramètres de deux façons:

  1. queryString, la participation de masse par queryString des restrictions de longueur, la valeur par défaut est 2048
  2. / Get / id

Notez le paramètre moyen point de passage:

  • paramètre querystring passage et obtenir / mode de demande après est les deux concepts, au lieu d'utiliser le passage de paramètre est querystring requête get, les paramètres POST peuvent également être transmis par querystring;
  • Lorsque le paramètre querystring passant par l' adresse de réception de fond n'est pas affectée, mais, si vous utilisez le mode de transmission get / id / référence doit d'arrière - plan / get /: id mode de paramètres de réception, et la valeur du paramètre est obtenu par ctx.params;

queryString paramètre mode de passage: l'exemple ci-dessus

« / Demander l'adresse / paramètre » paramètre Mode passe: en utilisant « / Adresse Demande /: le paramètre » reçoit l'adresse, les valeurs des paramètres acquises à l'aide ctx.params

<body>
    <button>点击发送get请求</button>
    <script>
        {
            //通过/get/3的方式进行传参,后台通过/get/:id进行获取,ctx.params得到具体参数值
            document.querySelector("button").onclick = function(){
                let xhr = new XMLHttpRequest();
                xhr.open("get","/getInfo/1");
                xhr.onload = function(){
                    console.log(xhr.responseText);//{"status":1,"msg":"请求成功"}
                }
                xhr.send();
            };
        }
    </script>
</body>

login.js:

//get请求
router.get("getInfo","/getInfo/:id",ctx=>{
    console.log(ctx.params);//{ id: '1' }
    ctx.body = {
        status:1,
        msg:"请求成功"
    };
});

Précautions 4.2post

poster généralement pas la participation massive queryString, parce que la participation de masse queryString longueur limitée (limite de serveurs), la valeur par défaut 2048.

passant poste de paramètre de référence est passé à travers le corps de HTTP, le corps doit être réglée pour passer paramètre codant pour le format . Formulaire avec le formulaire de format de codage par défaut <form action = "" enctype = "application / x-www-form-urlencoded"> </ form>. sous forme forme peut être omis, mais ne peut être omise lorsque ajax demande.

notes:

  1. Lors de la transmission des données à définir le format de texte http tête;
  2. Obtenir des informations en-tête: getAllResponseHeaders ou getResponseHeader;

- les données texte Envoyer lorsque vous devez définir le format http en-tête:

xhr.setRequestHeader("Content-type","application/x-www-form-urlencoded");  //默认编码
xhr.setRequestHeader("Content-type","multipart/form-data");  //二进制编码,上传文件时使用
xhr.setRequestHeader("Content-type","application/json");  //json编码:传输数据也需要时JSON格式

Exemple: On notera que l'utilisation de la requête après, le module KOA-corps d'arrière-plan doit être utilisé pour obtenir les paramètres

<body>
    <button>点击发送post请求</button>
    <script>
        {
            //通过/get/3的方式进行传参,后台通过/get/:id进行获取,ctx.params得到具体参数值
            document.querySelector("button").onclick = function(){
                let xhr = new XMLHttpRequest();
                xhr.open("post","/getPostInfo");
                xhr.onload = function(){
                    console.log(xhr.responseText);//{"status":1,"msg":"请求成功"}
                }
                //设置正文请求头
                xhr.setRequestHeader("content-type","application/x-www-form-urlencoded");
                let data = "username=zs&age=20";
                xhr.send(data);
            };
        }
    </script>
</body>
const koaBody = require("koa-body");
app.use(koaBody());
//post请求
router.post("/getPostInfo",ctx=>{
    console.log(ctx.request.body);//{ username: 'zs', age: '20' }
    
    ctx.body = {
        status:1,
        msg:"请求成功"
    };
});

Lorsque l'en-tête HTTP texte mis en forme comme JSON: format de transmission de données JSON est également nécessaire, vous devez utiliser le JSON.stringify () formater les données en JSON

 //正文请求头设置为json时,传输数据也需要是JSON格式
                xhr.setRequestHeader("content-type","application/json; charset=utf-8");
                let data = JSON.stringify({
                    username:'zs',
                    age:12
                });

  - Obtenez les informations d'en-tête: getAllResponseHeaders () Obtient toutes les informations d'en-tête ou getResponseHeader ( « attributs d'en-tête de demande ») qu'il faut une information d'en-tête

                xhr.onload = function(){
                    console.log(xhr.responseText);//{"status":1,"msg":"请求成功"}
                    //获取所有头部信息
                    console.log(xhr.getAllResponseHeaders());
                    //获取某个头部信息
                    console.log(xhr.getResponseHeader("content-type"));//application/json; charset=utf-8
                }

Résultats: Toutes les informations d'en-tête

Date: 18 septembre 2019 01:59:50 GMT
connexion: keep-alive
longueur de contenu: 33
-type de contenu: application / JSON; charset = UTF-8

4.3 Ajax synchrones et asynchrones

  • Set Asynchronous demande ou d'autres demandes pas d'incidence sur la mise en œuvre du code;
  • Lors de la configuration d'exécution synchrone, comme d'autres demandes ou code qui peuvent être exécutés après la demande, sera réalisée

Asynchronous: demande de réglage asynchrone ne modifie pas l'exécution de code ou d'autres demandes

<body>
    <button>按钮一</button>
    <button>按钮二</button>
    <script>
    {
        let btns = document.querySelectorAll("button");
        btns[0].onclick = function(){
            let xhr = new XMLHttpRequest();
            xhr.open("get","/getInfo/2",true);
            xhr.onload = function(){
                console.log(xhr.responseText);
            }
            xhr.send();
        }
        //点击第二个按钮时进行打印
        btns[1].onclick = function(){
            console.log("按钮二打印。。。");
            
        }
    }
    </script>
</body>

Résultat: Le bouton pour imprimer une demande ne modifie pas les résultats de deux boutons

 

Asynchronous: Lors du réglage de l'exécution synchrone, comme d'autres demandes ou code qui peuvent être exécutés après la demande, sera réalisée

 xhr.open("get","/getInfo/2",false);

 résultats:

 

5.onreadystatechange

5.1 onreadystatechange

onreadystatechange: il réponse du serveur de traitement fonctionnent à chaque fois que readyState change, la fonction onreadystatechange sera exécutée.

5.2 readyState

readyState: informations de réponse du serveur d'état là.

  • 0: La demande n'est pas initialisé (proxy est créé, mais pas encore appeler la méthode open ())
  • 1: connexion de serveur est établie ( `Méthode open` a été appelé)
  • 2: demande a été reçue ( `procédé send` a été appelé, et l'état et la tête est déjà disponible)
  • 3: Le processus de la demande (télécharger, `propriété responseText` contient déjà des données partielles)
  • 4: demande a été complétée, et la réponse est prête (opération de téléchargement est terminée)

5.3 Statut codes d'état commun

Union Statut Code de statut --http
code d'état HTTP description

100

Continuer. La partie restante continue de répondre, envoyez une demande

200

succès

301

mouvement permanent. Demander des ressources en permanence à un nouvel emplacement

302

Déménagement temporaire. demande de ressources zéro à un nouvel emplacement

304

Sans modification. Que la dernière demande de la ressource ne soit pas modifiée, la réponse ne contient pas le contenu des ressources

401

Requiert une authentification non autorisée

403

Interdit. Demande est refusée

404

Pas trouvé, le serveur n'a pas besoin de trouver des ressources

500

Erreur interne du serveur. Le serveur a rencontré une erreur et ne peut pas répondre à la demande

503

Serveur est indisponible. Service temporaire surchargé et ne peut pas traiter la demande

exemple: 

<body>
    <button>点击</button>
    <script>
        document.querySelector("button").onclick = function(){
            let xhr = new XMLHttpRequest();
            xhr.open("get","/getInfo/3",true);
            xhr.onreadystatechange = function(){
                //判断服务求响应状态为4和返还状态200(成功)
                if(xhr.readyState == 4){
                    if(xhr.status == 200){
                        console.log(xhr.responseText);//{"status":1,"msg":"请求成功"}
                    }
                }
            }
            xhr.send();
        };
    </script>
</body>

 En fait, on utilise des informations de réponse du serveur onload et renvoie un code d'état: onload sera plus concis recommandé

xhr.onload = function(){
                console.log(xhr.readyState);//4
                console.log(xhr.status);//200
                console.log(xhr.responseText);//{"status":1,"msg":"请求成功"}
            }

5.4 Retour de type de données  

  • Le serveur a renvoyé des données JSON: xhr.responseText pour obtenir
xhr.responseText  //来获取
  • données XML Server retour:
  1. xhr.responseXML // obtenir la valeur
  2. serveur de réponse fourni dans le ctx.set de contenu de type de contenu ( "content-type", "text / html");
  3. Réécriture XML distale (arrière de type type de contenu est non spécifié): xhr.overrideMimeType ( 'text / xml; charset = utf-8') Notez que la propriété peut être pas d'espace entre la
xhr.responseXML //获取值

 exemple:

HTML-end avant:

<body>
    <button>点击获取XML数据</button>
    <script>
    {
        document.querySelector("button").onclick = function(){
            let xhr = new XMLHttpRequest();
            xhr.open("get","/getXMLInfo",true);
            //如果后台没有设置XML的content-type,前端就必须重写格式
            xhr.overrideMimeType('text/xml;charset=utf-8');
            xhr.onload = function(){
                //获取XML格式数据
                console.log(xhr.responseXML);
                console.log(xhr.responseXML.getElementsByTagName("name")[0]);
                //获取原始数据
                console.log(xhr.response);
                
            }
            xhr.send();
        }
    }
    </script>
</body>

contexte:

//获取XML数据
router.get("/getXMLInfo",ctx=>{
    ctx.set("content-type","text/xml");
    //注意这里反引号和xml内容不能换行
    ctx.body = `<?xml version='1.0' encoding='utf-8' ?>
        <books>
            <nodejs>
                <name>nodeJS实战</name>
                <price>52.0元</price>
            </nodejs>
            <react>
                <name>react进阶</name>
                <price>56.0元</price>
            </react>
        </books>`;
});

 résultats:

Pour éviter l'arrière-plan ne pas écrire le type de contenu XML, besoin de réécrire le format XML à l'avant:

xhr.overrideMimeType('text/xml;charset=utf-8');

6. Utilisez FormData pour envoyer des fichiers

6.1 Création d'objets FormData

notes:

  1. <Input type = classe « file » = « monfichier »> acquis par le tableau est les fichiers des attributs de classe;
  2. Créer un objet de téléchargement de fichiers par le biais de nouveaux FormData ();
  3.  formData.append (nom, valeur), le nom du nom doit être compatible avec l'arrière-plan lors de la réception, la valeur peut être un fichier de données normale
  4. Téléchargement de fichiers doit être transmis par l'intermédiaire du texte, il est nécessaire d'utiliser la demande de poste, le type de contenu définit automatiquement l'utilisation FormData, vous n'avez pas besoin d'être réglés manuellement
  5. Après avoir reçu les données d'arrière-plan, l'attribut de nom () peut être obtenu dans les données correspondantes ou ajouter des fichiers distale
  6. Ensuite, vider les fichiers fs correspondant au module. Ce fichier ctx.request.files.img.path de chemin temporaire, vidage sur le chemin vers le fichier du serveur à un chemin temporaire
  7. Il est possible des problèmes d'autorisations de dossier, vous devez ouvrir manuellement les autorisations de fichier de vidage. Et le dossier n'existe pas, créez un dossier

exemple:

avant:

<body>
    <input type="file" class="myfile">
    <button>点击上传</button>
    <script>
        document.querySelector("button").onclick = function(){
            let myfile = document.querySelector(".myfile");
            //files属性返回的是类数组
            let files = myfile.files;
            //创建FormData对象,进行上传
            let formData = new FormData();
            //img表示name,相当于form表单中的name属性,file[0]表示要上传的单个文件
            formData.append("img",files[0]);
            //其他的数据,也可以进行传输
            formData.append("username","张三");

            //文件上传必须通过正文方式进行传递,所以必须使用post请求
            //使用FormData时会自动对content-type进行设置,就不需要再进行手动设置
            let xhr = new XMLHttpRequest();
            xhr.open("post","/upload",true);
            xhr.onload = function(){
                console.log(xhr.responseText);
            };
            xhr.send(formData);
        };
    </script>
</body>

contexte:

const Koa = require("koa");
const Router = require("koa-router");
const static = require("koa-static");
const koaBody = require("koa-body");
const fs = require("fs");

let app = new Koa();
let router = new Router();
app.use(static(__dirname + "/static"));
//上传文件时,必须设置允许文件上传,否则接收不了
app.use(koaBody({
    multipart:true
}));

//上传文件
router.post("/upload",ctx=>{
    //通过前端append()中的name属性即可获取到对应数据或文件
    // console.log(ctx.request.body);//{ username: '张三' }
    // console.log(ctx.request.files.img);
    //通过fs模块对相应文件进行转存即可
    //ctx.request.files.img.path即文件的临时路径,对临时路径中的文件转存到服务器下路径即可
    let fileData = fs.readFileSync(ctx.request.files.img.path);
    //文件转存时有可能出现文件夹权限问题,需要手动开启权限
    //判断文件夹不存在,需要先创建文件夹
    if(!fs.existsSync("static/imgs")){
        fs.mkdirSync("static/imgs/");
    }
    fs.writeFileSync("static/imgs/"+ctx.request.files.img.name,fileData);
    
    ctx.body = {
        status:1,
        msg:"文件上传成功"
    };
});

app.use(router.routes());
app.listen("8888");

 Les résultats: { "status": 1, "msg": "Fichier téléchargé avec succès"}

6.2 surveiller l'événement --upload de progression de téléchargement

Les événements suivants sont sous les événements de téléchargement:

  • onLoadStart commencer à télécharger
  • transfert de données dans onprogress (evt.total: taille totale à transmettre; evt.loaded: télécharger la taille du fichier en cours;)
  • onabort opération de chargement de mettre fin à (annuler le transfert xhr.abort ())
  • onerror téléchargement a échoué
  • onload téléchargé avec succès
  • onloadend téléchargement est terminé (que ce soit réussi ou non)

  Fichier progression du téléchargement des exemples de suivi:

notes:

  • Surveiller la vitesse de téléchargement de fichiers (nécessite onLoadStart et le décalage horaire onprogress et le fichier de différence de temps la taille du fichier téléchargé), la différence la taille du fichier / heure actuelle, le document vitesse de téléchargement;
  • unités de traitement doivent télécharger b / s kb / s;

Page de téléchargement du fichier:

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <meta http-equiv="X-UA-Compatible" content="ie=edge">
    <title>Document</title>
    <style>
    .progressSpan{
        display: none;
        color: seagreen;
    }

    </style>
</head>
<body>
    <input type="file" class="myfile">
    进度:<progress value="0" max="100"></progress>&nbsp;&nbsp;<span class="progressSpan">10%</span>&nbsp;&nbsp;
    速度:<span class="speed">20b/s</span><br><br>
    <button>点击上传</button>
    <button>取消上传</button>
    <script>
    {
        let btns = document.querySelectorAll("button");
        let xhr = new XMLHttpRequest();
        btns[0].onclick = function(){
            let sTime = 0;//文件开始上传时间
            let eTime = 0;//文件开始上传时间
            let fileInitSize = 0;//文件开始上传大小
            xhr.open("post","/fileUpload",true);
            //获取上传文件
            let file = document.querySelector(".myfile").files[0];
            let formData = new FormData();
            formData.append("imgFile",file);

            //upload事件监控文件上传进度
            xhr.upload.onloadstart = function(){
                console.log("文件开始上传");
                sTime = new Date().getTime();
                fileInitSize = 0;
            };
            xhr.upload.onprogress = function(evt){
                console.log("文件上传中");
                //在onprogress事件中监控上传进度
                let progress = (evt.loaded / evt.total * 100).toFixed(0);
                //将进度进行显示
                document.querySelector("progress").value = progress;
                document.querySelector(".progressSpan").style.display = "inline-block";
                document.querySelector(".progressSpan").innerHTML = progress+"%";

                //监控文件上传速度(需要onloadstart和onprogress的时间差,及时间差内文件已上传的文件大小)
                eTime = new Date().getTime();
                //需要将时间差转为秒s
                let diffTime = (eTime-sTime)/1000;
                //各个进度文件上传的文件大小
                let curFileSize = evt.loaded;
                let diffFileSize = curFileSize - fileInitSize;
                //获取上传速度(需要处理上传的单位b/s kb/s)
                let speed = diffFileSize/diffTime;
                let unit = "";
                if(speed/1024>1){
                    speed = speed/1024;
                    unit = "b/s";
                }
                if(speed/1024>1){
                    speed = speed/1024;
                    unit = "kb/s";
                }
                document.querySelector(".speed").innerHTML = speed.toFixed(2)+unit;
                //使用当前文件大小/时间差 即文件上传速度
                sTime = eTime;
                fileInitSize = curFileSize
            };
            xhr.upload.onabort = function(){
                console.log("取消文件上传");
            };
            xhr.upload.onerror = function(){
                console.log("文件上传失败");
            };
            xhr.upload.onload = function(){
                console.log(xhr.responseText);
            };
            xhr.upload.onloadend = function(){
                console.log("文件上传完成");
            };
            xhr.send(formData);
        };
        btns[1].onclick = function(){
            //取消文件上传方法
            xhr.abort();
        };
    }
    </script>
</body>
</html>

Traitement de fond:

//监控文件上传进度
router.post("/fileUpload",(ctx,next)=>{
    //通过前端append()中的name属性即可获取到对应数据或文件
    //ctx.request.files.imgFile.path即文件的临时路径,对临时路径中的文件转存到服务器下路径即可
    let fileData = fs.readFileSync(ctx.request.files.imgFile.path);
    
    //判断文件夹不存在,需要先创建文件夹
    if(!fs.existsSync("static/imgs")){
        fs.mkdirSync("static/imgs/");
    }
    fs.writeFileSync("static/imgs/"+ctx.request.files.imgFile.name,fileData);
    
    ctx.body = {
        status:1,
        msg:"文件上传成功"
    };
});

 résultats:

7. rappelle

1.ajax utilisation de base: créer l'objet XMLHttpRequest, xhr.open (), xhr.onload, xhr.send ()

2.Get / poste en cours d'utilisation dans ajax

3.ajax le retour réussi: onload

4. Le format de données renvoyées: réponse, responseText, responseXML

Objets 5.FormData: Créer des objets formData, form.append (nom, valeur)

méthode de suivi de l'événement pour chaque téléchargement de fichier: objet événement 6.upload

Publié 95 articles originaux · louange 115 won · vues 120 000 +

Je suppose que tu aimes

Origine blog.csdn.net/qq_34569497/article/details/100917080
conseillé
Classement