当前位置: 首页 > news >正文

长沙做网站建设的手机百度高级搜索

长沙做网站建设的,手机百度高级搜索,做网站页面怎么做,网站app怎么做功能: 1.多文件同时上传、2.拖动上传、3.实时上传进度条、4.中断上传和删除文件、5.原生file控件的美化 搁置的功能: 上传文件夹、大文件切片上传、以及其他限制条件未处理 Node服务器的前置准备: 新建文件夹: file_upload_serve初始化npm: npm …

请添加图片描述功能: 1.多文件同时上传、2.拖动上传、3.实时上传进度条、4.中断上传和删除文件、5.原生file控件的美化

搁置的功能: 上传文件夹、大文件切片上传、以及其他限制条件未处理

Node服务器的前置准备:

新建文件夹:		       file_upload_serve初始化npm:		       npm init -y安装工具:		       npm add express multernodemon工具:           npm install nodemon -gaxios:                 npm  install  axios  -sNode运行版本:  18.17.1修改package.json文件"scripts": {"test": "echo \"Error: no test specified\" && exit 1"},
改为:监听app.js"scripts": {"dev": "nodemon ./app.js"},
启动: npm run dev

Node > file_upload_serve > app.js

按前置准备完成,其他无需更改,请求部分全在app.js
在这里插入图片描述

/** @Description: * @Last Date: Do not edit*/
const express = require('express')
// post请求解析body
const bodyParser = require('body-parser')
// 上传工具库
const multer = require('multer')
const { writeFileSync } = require('fs')
const { resolve } = require('path')
const path = require('path')
const fs = require('fs')const app = express()
app.use(bodyParser.json({limit: '10mb', extended: true}))
// 静态资源共享(下载需要)
app.use(express.static(path.join(__dirname, 'public')))
// const storage = multer.diskStorage({
//   destination: function (req, file, callback) {
//     // 第一个参数: errorMessage;  参数2: 目标,即下载到哪个文件夹下
//     callback(null, 'uploads/')
//   },
//   filename: function (req, file, callback) {
//     // 获取上传文件的后缀名
//     const ext = file.originalname.split('.')[1]
//     callback(null, Date.now() + '.' + ext)
//   }
// })
const storage = multer.diskStorage({destination: (req, file, cb) => {cb(null, 'uploads/') // 分片存储目录},filename: (req, file, cb) => {const ext = file.originalname.split('.')[1]if(req.body.rename) {cb(null, Date.now() + '.' + ext) // 单文件名} else {cb(null, `${req.body.index}-${req.body.fileName}`) // 分片文件名}}
})// 生成upload对象
const upload = multer({storage,
})// 设置请求头
app.all('*', (req, res, next) => {// 允许所有不同源的地址访问res.header('Access-Control-Allow-Origin', '*');// 跨域允许的请求方式res.header('Access-Control-Allow-Methods', 'GET, POST');// x-ext: 获取文件的后缀名// res.header('Access-Control-Allow-Headers', 'Content-Type, x-ext');// res.header('Access-Control-Allow-Headers', 'Content-Type');res.header("Access-Control-Allow-Headers", "Origin, X-Requested-With, Content-Type, Accept, x-ext");if (req.method.toLowerCase() == 'options'){res.send(200);  //让options尝试请求快速结束} else {next()}})/* 上传方式1: multipart/form-data** upload.single  单文件上传*/
app.post('/file', upload.single('file'), (req, res) => {if(req.file){res.send('formData上传成功')} else {res.send('form-data上传失败')}
})/* 上传方式2: base64** upload.single  单文件上传*/
app.post('/base64', (req, res) => {const { file, ext, fileName } = req.bodyconst binaryData = Buffer.from(file, 'base64')if(!fileName) {writeFileSync(resolve(__dirname, 'uploads/' + Date.now() + '.' + ext), binaryData, 'binary')} else {writeFileSync(resolve(__dirname, 'uploads/' + fileName), binaryData, 'binary')}res.send('base64文件流上传成功')
})/* 上传方式3: binary 二进制** upload.single  单文件上传*/
app.post('/binary', (req, res) => {const ext = req.headers['x-ext']const buffers = []req.on('data', chunk => {buffers.push(chunk)}).on('end', () => {const binaryData = Buffer.concat(buffers)writeFileSync(resolve(__dirname, 'uploads/' + Date.now() + '.' + ext), binaryData, 'binary')res.send('二进制流上传成功')})
})
/* 多文件上传: formData** upload.array('formData中的字段名', 最大上传数量): */
app.post('/files', upload.array('files', 4), (req, res) => {console.log(req.files)if(req.files){res.send('多文件formData上传成功')} else {res.send('多文件formData上传失败')}
})
/* 文件下载* __dirname: 代表当前文件<app.js>所在的文件路径*/
app.get('/download', (req, res) => {try{// 下载路径: __dirname 拼接 第二个参数的路径const filePath = path.join(__dirname, '/public/download/1731726859151.txt')res.download(filePath)}catch(e){console.log(e)}})app.post('/merge', async (req, res) => {const uploadPath = '/uploads'let files = fs.readdirSync(path.join(process.cwd(), uploadPath)) // 获取所有的分片数据console.log(files)console.log(req.body.fileName)files = files.sort((a, b) => a.split('-')[0] - b.split('-')[0]) // 将分片按照文件名进行排序const writePath = path.join(process.cwd(), uploadPath, `${req.body.fileName}`) // 生成新的文件路径files.forEach((item) => {fs.appendFileSync(writePath, fs.readFileSync(path.join(process.cwd(), uploadPath, item))) // 读取分片信息,追加到新文件路径尾部fs.unlinkSync(path.join(process.cwd(), uploadPath, item)) // 将读取过的分片进行删除})res.send('ok')
})app.listen(8888, () => {console.log("链接成功")})

客户端

 
<!--* @Description:  功能: 1.多文件同时上传、2.拖动上传、3.实时上传进度条、*                      4.中断上传和删除文件、5.原生file控件的美化* 搁置的功能: 上传文件夹、大文件切片上传、以及其他限制条件未处理* @Last Date: Do not edit
-->
<template><div class="container"><header><divclass="box"@drop="handleClick"@dragenter="handleClick"@dragover="handleClick"@dragleave="handleClick"><div class="box-font"><div><span style="display: flex; align-items: center"><i class="el-icon-upload"> </i><p>将目录或多个文件拖拽到此进行扫描</p></span></div><div><span>支持的文件类型: .JPG.JPEG.BMP.PNG.GIF.ZIP</span></div><div><span>每个文件允许的最大尺寸: 1M</span></div></div></div></header><main><div class="main-choose-files-btn"><div class="file-box"><input type="button" class="btn" value="选择文件" /><inputtype="file"class="file"@change="previewMoreFilesByFormData"multiple/></div><div class="file-box"><input type="button" class="btn" value="选择文件夹" /><inputtype="file"class="file"@change="previewMoreFilesByFormData"multiple/></div></div><div><el-table :data="tableData" stripe style="width: 85%"><!-- <el-table-columnv-for="item in tableColumn":key="item.prop":prop="item.prop":label="item.label"></el-table-column> --><el-table-columnprop="name"label="文件名"width="240"fixed></el-table-column><el-table-column prop="type" label="类型"></el-table-column><el-table-column prop="size" label="大小"></el-table-column><el-table-column prop="state" label="状态"><!-- 当template中有多个元素需要切换时,需要在最外层使用div将所有元素包裹住 --><!-- slot-scope="scope" 必须加,否则数据不是响应式的 --><template slot-scope="scope"><div><divv-show="scope.row.progressPercent > 0 &&scope.row.progressPercent < 100"><el-progress:text-inside="true":stroke-width="15":percentage="scope.row.progressPercent"/></div><divv-show="scope.row.progressPercent < 1"slot="reference"class="name-wrapper"><el-tag size="medium"> 待上传 </el-tag></div><divv-show="scope.row.progressPercent === 100"slot="reference"class="name-wrapper"><el-tag size="medium"> 已上传 </el-tag></div></div></template></el-table-column><el-table-column label="操作"><template slot-scope="scope"><i class="el-icon-delete" @click="deleteFile(scope.row)"></i></template></el-table-column></el-table></div></main><footer><el-row><el-button class="foot-btn" size="mini"><span>文件数量: {{ tableData.length }}</span></el-button><el-button class="foot-btn" type="success" plain size="mini">成功数量: {{ successCount }}</el-button><el-button class="foot-btn" size="mini"><span>总大小: {{ countSize }} MB</span></el-button></el-row><el-row class="upload-btn"><el-buttontype="primary":disabled="uploadDisabled"@click="handelUploadMoreFile">开始上传</el-button></el-row></footer></div>
</template><script>
import axios from "axios"
export default {data() {return {ext: undefined, // 文件后缀名tableData: [],tableColumn: [{ prop: "name", label: "文件名" },{ prop: "type", label: "类型" },{ prop: "size", label: "大小" },{ prop: "progressPercent", label: "状态" },{ prop: "option", label: "操作" },],filesNumber: 1, // 列表文件总条数successCount: 0, // 上传成功条数cancelTokens: [], // 存储每个请求的取消方法}},mounted() {// 阻止事件冒泡,防止在拖拽后意外打开新标签页document.body.ondrop = function (event) {event.preventDefault()event.stopPropagation()}},computed: {getByte() {return this.tableData.reduce((a, b) => {return a + b.size}, 0)},// 文件总大小countSize() {return (this.getByte / 1048576).toFixed(2)},// 是否禁用"上传按钮"uploadDisabled() {return this.tableData.length > 0 ? false : true},},methods: {// 读取多个文件previewMoreFilesByFormData(e, drop) {let filesif (!drop) {files = e.target.files} else {files = e}// 获取文件后缀名this.ext = files[0].name.split(".")[1]if (!files) returnvar i = 0var _this = thisvar funcs = function () {if (files[i]) {var reader = new FileReader()reader.onload = function (e) {const uint8Array = new Uint8Array(e.target.result)const str = uint8Array.reduce((prev, byte) => {prev += String.fromCharCode(byte)return prev}, "")let now = new Date()// 由于JS执行速度很快,极大可能会得到一样的时间戳,故将timestamp加上下标// timestamp的作用是在将来删除文件时,作为唯一id对比删除let timestamp = now.getTime()// 将预览的文件中数据转换到table中_this.tableData.push({timestamp: timestamp + i,name: files[i].name,type: files[i].type,size: files[i].size,progressPercent: 0,dataBase64: btoa(str),})// progressPercent  上传进度条i++funcs() // onload为异步调用}reader.readAsArrayBuffer(files[i])}}funcs()},/** 删除上传文件* 不能通过数组下标去删。删除再添加新文件时,下标会重复* @param row(行数据)*/deleteFile(row) {// 删除文件this.tableData = this.tableData.filter((item) => item.timestamp !== row.timestamp)// 中断请求const requestToCancel = this.cancelTokens.find((token) => token.requestId === row.requestId)if (requestToCancel && requestToCancel.cancel) {requestToCancel.cancel("Request was canceled by the user.")}},// 上传文件handelUploadMoreFile() {let _this = thisconst CancelToken = axios.CancelTokenconst List = []for (let i = 0; i < this.tableData.length; i++) {// console.log(source.cancel)const ext = this.ext // 文件后缀名// 为每个请求创建一个新的取消令牌源const cancelTokenSource = CancelToken.source()this.cancelTokens.push({requestId: i,cancel: cancelTokenSource.cancel,})// 给tableData设置"requestId",将来取消请求通过比对id对应到具体的请求this.tableData[i].requestId = ivar a = axios({url: "http://localhost:8888/base64",method: "post",cancelToken: cancelTokenSource.token,data: {ext,fileName: this.tableData[i].name,file: this.tableData[i].dataBase64,},onUploadProgress: (progressEvent) => {/**  上传进度条*   progressEvent.loaded: 已上传文件大小*   progressEvent.total:  被上传文件的总大小*/_this.tableData[i].progressPercent =(progressEvent.loaded / progressEvent.total) * 100},}).then((res) => {// this.$message({//     message: '文件上传成功',//     type: 'success'//   })// console.log(res)}).catch((error) => {if (axios.isCancel(error)) {console.log(error.message)} else {console.log(error.message)}})List.push(a)}// 合并异步上传Promise.all(List).then((res) => {}).catch((err) => {})},// 处理鼠标拖放事件handleClick(e) {if (e.type == "dragenter") {// this.className = "drag_hover"}if (e.type == "dragleave") {// this.className = ""}if (e.type == "drop") {var files = e.dataTransfer.filesthis.className = ""if (files.length != 0) {this.previewMoreFilesByFormData(files, "drop")}}if (e.type == "dragover") {// e.dataTransfer.dragEffect = "copy"}},},
}
</script><style lang="scss">
body,
html {list-style: none;padding: 0;margin: 0;
}
.container {width: 85%;margin: 25px auto;.box {width: 85%;height: 300px;border-style: dashed; // border虚线border-width: 1px;margin-bottom: 20px;display: flex; /* 启用 Flexbox */justify-content: center; /* 水平居中 */align-items: center; /* 垂直居中 */.box-font {display: flex;flex-direction: column;align-items: center;gap: 30px;span {display: block;}}}main {.main-choose-files-btn {display: flex;gap: 100px;height: 44px;}}footer {margin-top: 20px;.upload-btn {margin-top: 10px;}}
}
// 对原生file控件优化
.btn,
.file {@extend .merge-input;
}
.merge-input {// display: block;position: absolute;width: 75px;height: 35px;color: #fff;border-radius: 4px;border-color: #409eff;
}
.btn {z-index: 2;background: #409eff; //  #66b1ff    409effpointer-events: none; /* 让事件传递到下一层,即: btn的层级比file高,但btn能触发file的事件 */
}
.file {z-index: 1;
}
// el-table表头样式修改
.el-table th {font-size: 13px;font-weight: 700;
}.el-table .el-table__header th,
.el-table .el-table__header tr,
.el-table .el-table__header td {background: #f5f8fd;
}.el-icon-upload {font-size: 35px;
}
</style>
http://www.tj-hxxt.cn/news/119019.html

相关文章:

  • 动态网站制作报价游戏优化是什么意思
  • 公司网页设计培训课程哈尔滨优化网站方法
  • 论坛类网站搭建附近电脑培训班位置
  • 传奇三端互通新开服网站app拉新推广平台渠道商
  • 曲阜市网站建设好f123网站
  • 苹果电脑做网站设计宁波网站推广方式
  • 合肥营销型网站建设开发seo优化的内容有哪些
  • 网站做统计网络销售入门基本知识
  • 珠海网站优化公司西安网站seo工作室
  • 怎样开通app软件郑州网站优化seo
  • 做网站banner分辨率设置多大企业网络组建方案
  • 做营销网站的企业长春网站制作公司
  • 现在大家做电商网站用什么源码大数据获客系统
  • 中国建设银行公积金网缴网站视频营销的策略与方法
  • 做网站和做网店哪个好nba最新消息交易情况
  • 如何做网站页面河北百度seo关键词排名
  • 做装修网站多少钱sem分析是什么
  • 深圳建站推广公司网络营销模式下品牌推广研究
  • 永川网站制作seo做得比较好的企业案例
  • 昆明电子商务网站建设中国十大网站排名
  • 网站建设该如何学软件开发流程
  • wordpress怎样做单页网站临沂百度seo
  • wordpress接入翼支付宝seo的概念是什么
  • 常德网站建设详细策划淘宝关键词推广
  • 上海高端网站设计外链发布平台有哪些
  • 网站改版怎样做301地域名网址查询
  • 阿里巴巴外贸网站首页sem推广是什么意思
  • 大型网站开发案例深圳营销型网站
  • 青岛济南网站制作石家庄关键词排名首页
  • 网站栏目页面潍坊自动seo