ajax实现文件上传

核心两点

核心:上传文件最主要的两个核心:

  • post: 可以上传文文本和二进制数据(图片、视频、音频、)

  • 设置请求头Content-type:

    Content-type','application/x-www-form-urlencoded : 会把数据编码之后当做文本传输
    Content-type','multipart/form-data : 可以传递文本和二进制数据(实现文件的上传)
    Content-type: "text/plain"
    
    

传统方式上传(页面跳转)

使用node的第三方包实现文件上传,

multer

基本使用:

服务端server.js:

const express = require('express');
const path = require('path')
const fs = require('fs');
const multer = require('multer');
const app = express();

// 定义上传的目录
var upload = multer({ dest: 'uploads/' })


// 托管静态资源
app.use('/uploads',express.static(path.join(__dirname,'uploads')))



app.get('/form',(req,res)=>{
    res.sendFile(path.join(__dirname,'form.html'))
})

app.get('/formajax',(req,res)=>{
    res.sendFile(path.join(__dirname,'form-ajax.html'))
})

app.get('/ajax',(req,res)=>{
    res.sendFile(path.join(__dirname,'ajax.html'))
})

app.get('/formjqueryajax',(req,res)=>{
    res.sendFile(path.join(__dirname,'form-jquery-ajax.html'))
})

//实现文件上传
app.post('/upload',upload.single('avatar'),(req,res)=>{
    console.log(req.body); //接收文本 text
    console.log(req.file); //接收文件上传成功后的信息
    if(req.file){
        // 进行文件的重命名即可 fs.rename
        let {originalname,destination,filename} = req.file;
        let dotIndex = originalname.lastIndexOf('.');
        let ext = originalname.substring(dotIndex);
        let oldPath = `${destination}${filename}`;
        let newPath = `${destination}${filename}${ext}`;
        fs.rename(oldPath,newPath,err=>{
            if(err){ throw err; }
            res.json({message:'上传文件成功','path':newPath})
        })
    }else{
        res.json({message:'没有上传文件'})
    }
    
    
})

app.listen(4000,_=>console.log('服务器已经启动port4000'))

form.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">
    <title>Document</title>
</head>
<body>
    <h2>传统方式上传(页面会跳转)</h2>
    <form action="/upload" method='post' enctype="multipart/form-data">
        <div>
            用户名: <input type="text" name="username">
        </div>
        <div>
            密码: <input type="password" name="password">
        </div>
        <div>
            头像: <input type="file" name="avatar">
        </div>
        <div>
            <input type="submit" value="提交">
        </div>
    </form>
</body>
</html>

传统的ajax上传 配合FormData

form-ajax内容:

<!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>
        form img {
            width: 150px;
            vertical-align: middle;
        }
    </style>
</head>
<body>
    <h2>原生ajax实现文件上传</h2>
    <form id="theForm">
        <div>
            用户名: <input type="text" name="username">
        </div>
        <div>
            密码: <input type="password" name="password">
        </div>
        <div>
            头像: <input type="file" name="avatar">
        </div>
        <div>
            预览:
            <img src="" alt="" id="preview">
        </div>
        <div>
            <input type="button" id="btn" value="提交">
        </div>
    </form>
</body>
<script>
    let btn = document.getElementById('btn');
    let theform = document.getElementById('theForm')
    let preview = document.getElementById('preview')
    btn.onclick = function(){
        let xhr = new XMLHttpRequest();
        xhr.onload = function(){
            let data = JSON.parse(this.responseText);
            let {path,message} = data;
            // 实现图片预览
            path &&  (preview.src = path);
            alert(message)

        }
        xhr.open('post',"/upload",true)
        // 创建FormData,携带表单数据
        let formData = new FormData(theform); // 自动收集表单含name属所有字段数据
        formData.append('email','luoluo@qq.com')
        xhr.send(formData);
       
    }
</script>
</html>

或:

ajax.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">
    <title>Document</title>
    <style>
        form img {
            width: 150px;
            vertical-align: middle;
        }
    </style>
</head>
<body>
    <h2>原生ajax实现文件上传</h2>
    <div>
        用户名: <input type="text" id="username" name="username">
    </div>
    <div>
        密码: <input type="password" id="password" name="password">
    </div>
    <div>
        头像: <input type="file"   id="avatar" name="avatar">
    </div>
    <div>
        预览:
        <img src="" alt="" id="preview">
    </div>
    <div>
        <input type="button" id="btn" value="提交">
    </div>
</body>
<script>
    let btn = document.getElementById('btn');
    let preview = document.getElementById('preview')
    let userEle = document.getElementById('username')
    let passEle = document.getElementById('password')
    let avatarEle = document.getElementById('avatar')
    btn.onclick = function(){
        let xhr = new XMLHttpRequest();
        xhr.onload = function(){
            let data = JSON.parse(this.responseText);
            let {path,message} = data;
            // 实现图片预览
            path &&  (preview.src = path);
            alert(message)

        }
        xhr.open('post',"/upload",true)
        // 创建FormData,携带表单数据
        let formData = new FormData(); // 自动收集表单含name属所有字段数据
        // 获取数据追加到FormData中
        let username = userEle.value;
        let password = passEle.value;

        formData.append('username',username)
        formData.append('password',password)
        // avatarEle.files[0]二进制数据 file
        formData.append('avatar',avatarEle.files[0])
        xhr.send(formData);
       
    }
</script>
</html>

jquery-$.ajax配合FormData

form-jquery-ajax.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">
    <title>Document</title>
    <style>
        form img {
            width: 150px;
            vertical-align: middle;
        }
    </style>
</head>
<body>
    <h2>jquery-$.ajax实现文件上传</h2>
    <form id="theForm">
        <div>
            用户名: <input type="text" name="username">
        </div>
        <div>
            密码: <input type="password" name="password">
        </div>
        <div>
            头像: <input type="file" name="avatar">
        </div>
        <div>
            预览:
            <img src="" alt="" id="preview">
        </div>
        <div>
            <input type="button" id="btn" value="提交">
        </div>
    </form>
</body>
<script src="https://cdn.bootcdn.net/ajax/libs/jquery/3.5.1/jquery.js"></script>
<script>
    let btn = $('#btn');
    let theform = $('#theForm')
    let preview = $('#preview')

    btn.on('click',()=>{
        // 收集表单的所有的数据
        let formData = new FormData(theform[0])
        let username = formData.get('username')
        let password = formData.get('password')
        let fileBin = formData.get('avatar')
        if(username === '' ||password===''){
            alert('用户名和密码都必填');
            return;
        }

        let size = fileBin.size; // 字节  1kb=1024byte  1mb = 1024kb
        if(size === 0){
            alert('必须上传帅照')
            return;
        }
        // 不能超过3m
        let mb = parseInt(size/1024/1024);
        if(mb > 3){
            alert('你的帅照太大,不能超过3兆');
            return
        }
        // 只能使用$.ajax 
        $.ajax({
            type: "post",
            url: "/upload",
            processData: false, // 告诉jquery不需要处理数据
            contentType: false, // 不需要设置编码
            data: formData,
            dataType: 'json',
        }).then(res=>{
            let {message,path} = res;
            path && preview.attr('src',path);
            alert(message)
        })

    })
   
</script>
</html>

文件下载

利用a标签download属性即可实现文件下载:

<a download href="uploads/002228af541123a5ab4fdf70a3a19b87.jpg">下载</a>
<a download='abcde' href="uploads/002228af541123a5ab4fdf70a3a19b87.jpg">下载</a>

此download属性指示浏览器下载URL而不是导航到URL,因此将提示用户将其保存为本地文件

download设置属性值可指定下载文件的名字


版权声明:本文为m0_50865651原创文章,遵循CC 4.0 BY-SA版权协议,转载请附上原文出处链接和本声明。