多文件上传(含node服务端)

多文件上传

app.js

const express = require('express')

const fs = require('fs')
const path = require('path')

const app = express()
const multipart = require('connect-multiparty')
const multipartHandler = multipart()

app.all('/*',(req,res,next) => {
    res.header('Access-Control-Allow-Origin','*')
    res.header('access-control-allow-methods','GET,POST,options')
    next()
})


const writeFile = (file) => {
    const tempPath = file.path
    let targetPath = './upload/' + file.name
    console.log('target',targetPath);
    fs.copyFile(tempPath, targetPath, (error) => {
        if (error) {
          console.error('Error moving file', error);
          res.status(500).send('Error moving file');
        } else {
          console.log(file.name+'插入成功')
        //   删除本条临时缓存数据
        fs.unlink(tempPath,(error) => {
            if(error) {
                console.log('删除'+file.name+'缓存失败');
            }
            else{
                console.log('删除'+file.name+'缓存成功');
            }
        })
        }
      });
}

app.post('/upload',multipartHandler,(req,res) => {
    console.log('body',req.body)
    console.log('files',req.files);
    let fileLen = req.files.file.length
    if (fileLen > 1) {
        let fileArr = req.files.file
        for(let key in fileArr) {
            let file = fileArr[key]
            console.log('file',file);
            writeFile(file)
        }
    }else {
        let file = req.files.file
        writeFile(file)
    }
    res.send({
        code:200,
        msg:'success'
    })
})

app.listen('9876',() => {
    console.log('文件上传端口已开启http://localhost:9876/upload')
})
connect-multiparty插件会在系统生成临时文件 即req.files.file.path 为临时路径,使用fs模块的copyFile移动到当前的目录下面之后使用fsunlink模块删除临时路径

在这里插入图片描述

前端

index.js
/** @return {HTMLElement} */
function $ (elAttr) {
    return document.querySelector(elAttr)
}

let uploadFileButton = $('#uploadFileButton')
let view = $('.container')
let tips = $('.inner-text')
let innerProgress = $('.inner-progress')
let loadText = $('.load-text')

function switchTips (flag){
    if(flag) {
        tips.style.display = 'block'
    }else {
        tips.style.display = 'none'
    }
}

view.ondrop = async function(e){
    view.style.border = '1px solid rgb(205 28 28)'
    e.preventDefault()
    console.log('e', e.dataTransfer.files);
    if(e.dataTransfer.files){
        const fileArr = Array.from(e.dataTransfer.files) // 类数组结构变为数组
        const fileForm = new FormData()
        for(let key in fileArr) {
            const url = URL.createObjectURL(fileArr[key])
            randomImg(url,fileArr[key].name)
            console.log('url地址',url);
            console.log('当前文件',fileArr[key]);
            fileForm.append('file',fileArr[key],fileArr[key].name)
        }
        let {data:res} = await uploadHttp(fileForm)
        console.log('多文件上传结果',res);
    }
}
view.ondragenter = function(e){
    console.log(e)
}

view.ondragover = function(e){
    // console.log(e);
    view.style.border = '1px solid rgb(205 28 28)'
    e.preventDefault()
}

view.ondragleave = function(e){
    console.log('结束',e);
    view.style.border = '1px solid #ccc'
}

// 上传文件处理函数
function uploadHttp(fileObj){
    return axios({
        method:"POST",
        url:"http://localhost:9876/upload",
        headers:{
            "Content-Type":"multipart/form-data"
        },
        data:fileObj,
        onUploadProgress: function(progressEvent) {
            const percentage = Math.round((progressEvent.loaded * 100) / progressEvent.total);
            console.log(`上传进度: ${percentage}%`);
            innerProgress.style.width = percentage + '%'
            loadText.innerText = '当前上传进度' + percentage + '%'
            if(percentage >= 100) {
                loadText.innerText = '上传完毕'
                switchTips(false)
            }
        }
    })
}


// 文件上传函数
async function uploadFileHandler (event){
    console.log('event',event);
    // 判断当前文件个数
    let len = event.target.files.length
    if (len > 1) {
        console.log('当前为多文件上传',event.target.files);
        const fileArr = Array.from(event.target.files) // 类数组结构变为数组
        const fileForm = new FormData()
        for(let key in fileArr) {
            const url = URL.createObjectURL(fileArr[key])
            randomImg(url,fileArr[key].name)
            console.log('url地址',url);
            console.log('当前文件',fileArr[key]);
            fileForm.append('file',fileArr[key],fileArr[key].name)
        }
        let {data:res} = await uploadHttp(fileForm)
        console.log('多文件上传结果',res);
    } else if (len == 1){
        console.log('当前为单文件上传',event.target.files);
        const url = URL.createObjectURL(event.target.files[0])
        console.log('url',url);
        randomImg(url,event.target.files[0].name)
        const fileForm = new FormData()
        fileForm.append('file',event.target.files[0])
        let {data:res} = await uploadHttp(fileForm)
        console.log('单文件上传结果',res);
    }
}

// 生成img
function randomImg (url,name){
    let img = document.createElement('img')
    img.src = url
    img.style.width = '60px'
    let p = document.createElement('p')
    p.innerText = name
    view.appendChild(img)
    view.appendChild(p)
}


uploadFileButton.addEventListener('change',(e) => {
    uploadFileHandler(e)
})


index.html
<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>多文件上传</title>
    <style>
        *{padding: 0px;margin: 0px;list-style: none;}
        .container {
            width: 600px;
            height: 200px;
            margin: 0 auto;
            display: flex;
            align-items: center;
            justify-content: center;
            flex-wrap: wrap;
            border: 1px solid #ccc;
            border-radius: 12px;
        }
        .container h5 {
            text-align: center;
        }
        .inner-text {
            text-align: center;
            color: #595555;
        }
        .progress {
            margin: 100px auto;
            width: 90%;
            height: 16px;
            border: 1px solid #ccc;
        }
        .inner-progress {
            width: 0%;
            height: 100%;
            background: #051488;
        }
    </style> 
</head>
<body>
    <div class="container">
        <h5 class="inner-text">拖动文件到这里上传 支持多文件上传</h5>
    </div>
    <input id="uploadFileButton" multiple type="file" placeholder="上传文件">
    <!-- 显示当前进度条 -->
    <div class="progress">
        <div class="inner-progress"></div>
        <p class="load-text">未选择文件上传</p>
    </div>
    <script src="./axios.min.js"></script>
    <script src="./index.js"></script>
</body>
</html>
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
好的,下面是一个基于JavaScript的前文件和大文件分片上的示例代码: 首先是HTML部分,使用input标签实现多文件选择和上按钮: ```html <input type="file" multiple id="file-input"> <button onclick="upload()">上</button> ``` 接下来是JavaScript部分,实现了多文件和大文件分片上功能。其中,upload函数是上按钮的点击事件处理函数。 ```javascript function upload() { const fileInput = document.getElementById('file-input'); const files = fileInput.files; const chunkSize = 1024 * 1024; // 分片大小为1MB const totalChunks = Math.ceil(files.size / chunkSize); // 计算总块数 for (let i = 0; i < files.length; i++) { const file = files[i]; const chunks = Math.ceil(file.size / chunkSize); // 计算当前文件的总块数 for (let j = 0; j < chunks; j++) { const start = j * chunkSize; const end = Math.min(start + chunkSize, file.size); const chunk = file.slice(start, end); // 构造FormData对象,用于上分片数据 const formData = new FormData(); formData.append('file', chunk); formData.append('fileName', file.name); formData.append('chunkIndex', j); formData.append('totalChunks', chunks); // 使用XMLHttpRequest进行上 const xhr = new XMLHttpRequest(); xhr.open('POST', '/upload'); xhr.send(formData); } } } ``` 以上代码中,我们先获取了input标签中选择的所有文件,然后对每个文件进行分片上。每个分片的大小默认为1MB,可以根据实际情况进行调整。接着使用FormData对象构造包分片数据的表单数据,然后使用XMLHttpRequest进行上。上的URL为`/upload`,可以根据实际情况进行调整。 在服务,我们需要接收上的分片数据,并在接收完所有分片后进行合并。以下是Node.js的示例代码: ```javascript const express = require('express'); const app = express(); const fs = require('fs'); const path = require('path'); app.use(express.json()); app.use(express.urlencoded({ extended: true })); app.post('/upload', (req, res) => { const file = req.body.file; const fileName = req.body.fileName; const chunkIndex = req.body.chunkIndex; const totalChunks = req.body.totalChunks; const filePath = path.join(__dirname, fileName + '.' + chunkIndex); // 将分片数据写入文件 fs.writeFile(filePath, file, (err) => { if (err) { console.error(err); res.status(500).send('Failed to write chunk data'); return; } // 如果是最后一个分片,则进行合并 if (chunkIndex === totalChunks - 1) { const writeStream = fs.createWriteStream(fileName); for (let i = 0; i < totalChunks; i++) { const chunkPath = path.join(__dirname, fileName + '.' + i); const chunkData = fs.readFileSync(chunkPath); writeStream.write(chunkData); fs.unlinkSync(chunkPath); // 删除已合并的分片文件 } writeStream.end(() => { res.send('Upload success'); }); } else { res.send('Chunk uploaded'); } }); }); app.listen(3000, () => { console.log('Server started at http://localhost:3000'); }); ``` 以上代码中,我们使用Express框架接收POST请求,并从请求体中获取分片数据、文件名、当前分片索引、总块数等信息。然后将分片数据写入文件,如果是最后一个分片,则进行合并,最终得到完整的文件。注意,分片文件的命名规则为`文件名.分片索引`,合并完成后需要删除已合并的分片文件。 这就是一个基于JavaScript的前文件和大文件分片上的实现示例,希望能对你有所帮助。

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值