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

Vue通过file控件上传文件到Node服务器

请添加图片描述功能: 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>

相关文章:

Vue通过file控件上传文件到Node服务器

功能&#xff1a; 1.多文件同时上传、2.拖动上传、3.实时上传进度条、4.中断上传和删除文件、5.原生file控件的美化 搁置的功能: 上传文件夹、大文件切片上传、以及其他限制条件未处理 Node服务器的前置准备: 新建文件夹: file_upload_serve初始化npm: npm …...

如何在 SQL Server 中新增账户并指定数据库权限

在日常的数据库维护与开发中,管理用户的权限是必不可少的一环。本文将指导你如何在 SQL Server 中为新用户创建账户,并为其指定相应的数据库权限,使其只能查看有权访问的数据。我们将以步骤和代码示例的方式展示整个流程。用户权限分配包括:读取权限、写入权限、执行权限。…...

c#编码技巧(十九):各种集合特点汇总

.NET 常用集合对比&#xff1a; .NET 常见的线程安全集合 .NET 只读集合...

汽车软件DevOps解决方案

汽车软件DevOps解决方案是专为现代汽车行业设计的一套集成化需求、开发、测试、部署、OTA与监控&#xff0c;旨在加速软件开发流程&#xff0c;提高软件质量和安全性&#xff0c;同时确保整个生命周期的高效性和灵活性。以下是经纬恒润汽车软件DevOps解决方案的关键组成部分和优…...

同步的意义以及机制

一、同步的意义 同步&#xff08;Synchronization&#xff09;的意义在于确保在多线程环境中&#xff0c;多个线程对共享资源的访问是安全的&#xff0c;避免竞争条件&#xff08;race conditions&#xff09;和数据不一致的情况。 具体来说&#xff0c;同步的核心目标是&…...

leetcode 面试150之 156.LUR 缓存

请你设计并实现一个满足 LRU (最近最少使用) 缓存 约束的数据结构。 实现 LRUCache 类&#xff1a; LRUCache(int capacity) 以 正整数 作为容量 capacity 初始化 LRU 缓存int get(int key) 如果关键字 key 存在于缓存中&#xff0c;则返回关键字的值&#xff0c;否则返回 -…...

启发式搜索算法复现

&#x1f3e1;作者主页&#xff1a;点击&#xff01; &#x1f916;编程探索专栏&#xff1a;点击&#xff01; ⏰️创作时间&#xff1a;2024年11月21日19点05分 神秘男子影, 秘而不宣藏。 泣意深不见, 男子自持重, 子夜独自沉。 论文链接 点击开启你的论文编程之旅…...

【IDE】使用指南

定期更新实用技能&#xff0c;建议关注收藏点赞。 友情链接&#xff1a; 点击跳转常见代码编辑器的报错解决方案 目录 常用快捷键pycharm右下角边栏脚本头安装IDE的插件git配置TODO 代码编辑器里有许多小技巧&#xff0c;便于办公。本篇主要以pycharm,vscode等主流常用IDE为…...

设计编程网站集:简述可扩展性系统设计(笔记)

视频连接&#xff1a;简述可扩展性系统设计 三个关键原则 无状态 松散耦合 异步处理 扩展 负载均衡 缓存 分片...

「Mac玩转仓颉内测版25」基础篇5 - 布尔类型详解

本篇将介绍 Cangjie 中的布尔类型&#xff0c;包括布尔值的定义、运算操作符、逻辑运算、布尔类型的常见应用场景及其在条件判断中的应用&#xff0c;帮助开发者理解和使用布尔类型。 关键词 布尔类型定义布尔运算逻辑运算符条件判断常见应用场景 一、布尔类型概述 布尔类型&…...

Fashion-VDM:引领视频虚拟试穿技术的新篇章

引言 随着虚拟现实和增强现实技术的飞速发展,视频虚拟试穿(VVT)已成为时尚产业的一大创新领域。然而,现有的VVT方法在服装细节和时间一致性方面仍存在诸多不足。为了解决这些问题,Johanna Karras等人提出了Fashion-VDM,一种基于视频扩散模型(VDM)的新型视频虚拟试穿技…...

Scala中的集合复习(1)

Map、Set、Array、List 一、集合的三大类 1.序列Seq表示有先后顺序的集合。&#xff08;Array、List&#xff09; 2.集Set&#xff1a;表示无序且不重复的集合。 3.映射Map&#xff1a;表示键值对。 Stack&#xff1a;栈&#xff0c;特点是&#xff1a;后进先出。 packag…...

Java依赖包漏洞检测命令

1、漏洞扫描工具 maven插件方式&#xff1a;Dependency-Check 2、命令 检查单个 Maven 工程的安全漏洞 mvn dependency-check:check 这个命令会在 target 目录下生成一个 dependency-check-report.html 文件&#xff0c;其中包含了依赖项的安全漏洞分析报告。 检查多个 M…...

【Java】强制类型转换

int a23; short b(short) a; 小的接受大的接受不了&#xff0c;强制类型转换. 带有Buffer的&#xff0c;带有流的&#xff0c;都是数组。 网络流&#xff0c;文件流都是数组. 这种就是流。 操作系统底层就是C. 没有直系关系的&#xff0c;不让转换 语法不报错&#xff0c;运行…...

RabbitMQ消息可靠性保证机制4--消费端限流

7.7 消费端限流 在类似如秒杀活动中&#xff0c;一开始会有大量并发写请求到达服务端&#xff0c;城机对消息进行削峰处理&#xff0c;如何做&#xff1f; 当消息投递的速度远快于消费的速度时&#xff0c;随着时间积累就会出现“消息积压”。消息中间件本身是具备一定的缓冲…...

查找萤石云IOS Sdk中的编解码接口

2021/1/20 以前的时候&#xff0c;碰到的问题&#xff0c;想把萤石云视频介入到TRTC&#xff0c;但是... 萤石云的IOS接口中没有相应的解码播放库&#xff0c;也就是找不到PlayerSDK对应部分&#xff0c;怎么做呢&#xff1f; 一个是坐等萤石云开放这部分接口&#xff0c;可能…...

erchas

#include <iostream> #include <vector> https://gitee.com/tongchaowei/front-native-page-template/tree/main/image-display/template-01 using namespace std; class BinaryTree { private: vector<char> tree; // 存储二叉树的数组 int size;…...

【网络安全】SSL(一):为什么需要 Keyless SSL?

未经许可,不得转载。 文章目录 背景正文背景 随着网站和应用程序向云端迁移,使用 HTTPS(SSL/TLS)加密流量已成为行业标准。然而,传统的 HTTPS 配置要求服务器持有网站的私钥,这在云计算环境中引发了一系列安全性和合规性问题。一旦云服务器遭到攻击,私钥泄露可能带来不…...

ggplot2 分面图等添加注释文字,相加哪里加哪里: 自定义函数 AddText()

如果分面图上还想再添加文字&#xff0c;只能使用底层的grid包了。 函数定义 # Add text to ggplot2 figures # # param label text you want to put on figure # param x position x, left is 0, right 1 # param y position y, bottom is 0, up 1 # param color text color…...

解读缓存问题的技术旅程

目录 前言1. 问题的突发与初步猜测2. 缓存的“隐身术”3. 缓存策略的深层优化4. 反思与感悟结语 前言 那是一个普通的工作日&#xff0c;团队例行的早会刚刚结束&#xff0c;我正准备继续优化手头的模块时&#xff0c;突然收到了用户反馈。反馈的内容是部分数据显示异常&#…...

洛谷P1597

语句解析 - 洛谷 语句解析 题目背景 木有背景…… 题目描述 一串长度不超过255的 PASCAL 语言代码&#xff0c;只有 a,b,c 三个变量&#xff0c;而且只有赋值语句&#xff0c;赋值只能是一个一位的数字或一个变量&#xff0c;每条赋值语句的格式是 [变量]:[变量或一位整数…...

2411rust,76~79

1.76.0稳定版 此版本较小 ABI兼容更新 函数指针文档中新增的ABI兼容部分介绍了函数签名与ABI兼容的意义.大部分是参数类型和返回类型的兼容,及在当前Rust中兼容的列表.文档仅描述现有兼容的状态. 一个新增功能是,现在保证符和u32是ABI兼容的.它们一直有相同大小和对齐方式,…...

vue2.0前端管理系统界面布局设置

前言 后台管理系统的核心就是用户管理、角色管理&#xff08;含权限分配&#xff09;、菜单管理&#xff0c;以及一些业务管理。业务管理通常以及根据不同的角色进行了权限分配。本次任务完成用户管理页面。 一 界面设计 1.引用Element 的Container 布局容器。 以上次博客中…...

4. SQL视图

MySQL中的视图&#xff08;View&#xff09;是一种虚拟表&#xff0c;本质是存储了一条SELECT语句。视图并不直接存储数据&#xff0c;而是动态生成结果集&#xff0c;帮助开发者简化查询逻辑和增强数据安全性。本文将从视图的基础概念到实际应用&#xff0c;逐步深入地探讨如何…...

Simulink学习笔记【PID UG联动仿真】

Simulink进行PID控制及调参&#xff1a; 建立系统动力学框图&#xff08;把状态方程翻译出来&#xff09;&#xff0c;设置成subsystem建立PID反馈回路。示波器叫scope&#xff0c;多变量输出用demux和mux。可以用自动调参Tune模块&#xff0c;调整响应速度和稳定性&#xff0…...

【Python】30个Python爬虫的实战项目!!!(附源码)

Python爬虫是数据采集自动化的利器。本文精选了30个实用的Python爬虫项目&#xff0c;从基础到进阶&#xff0c;每个项目都配有完整源码和详细讲解。通过这些项目的实战&#xff0c;可以全面掌握网页数据抓取、反爬处理、并发下载等核心技能。 一、环境准备 在开始爬虫项目前…...

uni-app 界面TabBar中间大图标设置的两种方法

一、前言 最近写基于uni-app 写app项目的时候&#xff0c;底部导航栏 中间有一个固定的大图标&#xff0c;并且没有激活状态。这里记录下实现方案。效果如下&#xff08;党组织这个图标&#xff09;&#xff1a; 方法一&#xff1a;midButton的使用 官方文档&#xff1a;ta…...

什么是Sass,有什么特点

Sass 概述 什么是 Sass&#xff1f; Sass&#xff08;Syntactically Awesome Style Sheets&#xff09;是一种 CSS 预处理器&#xff0c;它扩展了 CSS 的功能&#xff0c;使其更加强大和灵活。Sass 允许开发者使用变量、嵌套规则、混合宏、继承等高级特性&#xff0c;从而编写…...

服务器端渲染 (SSR) 与客户端渲染 (CSR)

嘿程序员&#xff01;我们都知道&#xff0c;新时代的 Javascript 已经彻底改变了现代网站的结构和用户体验。如今&#xff0c;网站的构建更像是一个应用程序&#xff0c;伪装成一个能够发送电子邮件、通知、聊天、购物、支付等的网站。今天的网站是如此先进、互动&#xff0c;…...

数据结构(Java版)第一期:时间复杂度和空间复杂度

目录 一、数据结构的概念 1.1. 什么是数据结构 1.2. 算法与数据结构的关系 二、算法效率 三、时间复杂度 3.1. 大O的渐进表⽰法 3.2. 计算冒泡排序的时间复杂度 3.3. 计算二分查找的时间复杂度 四、空间复杂度 4.1. 空间复杂度 4.2. 冒泡排序的空间复杂度 4.3.…...

高校网站建设需求单/泉州网站建设优化

策略模式【Strategy Pattern】刘备要到江东娶老婆了&#xff0c;走之前诸葛亮给赵云&#xff08;伴郎&#xff09;三个锦囊妙计&#xff0c;说是按天机拆开解决棘手问题&#xff0c;嘿&#xff0c;还别说&#xff0c;真是解决了大问题&#xff0c;搞到最后是周瑜陪了夫人又折兵…...

太原做网站培训/文案代写收费标准

前言 &#xff1a; 有很多时候看一些技术文章&#xff0c;总是停留在看的阶段&#xff0c;但是知识的学习在我看来分成三个步骤&#xff1a;first 。 了解-主要动作也就是看&#xff0c;或者听&#xff0c;比较浅显的学习方式&#xff0c;遗忘速度也比较快 &#xff1b; second…...

php动态网站开发教程/优化师是一份怎样的工作

1.strcpy函数原型&#xff1a;strcpy(str1,str2);功能&#xff1a;将字符串str2复制到字符串str1中&#xff0c;并覆盖str1原始字符串&#xff0c;可以用来为字符串变量赋值返回&#xff1a;str1注意&#xff1a;1)字符串str2会覆盖str1中的全部字符&#xff0c;2)字符串str2的…...

杭州专业网站建设/今日热点新闻排行榜

简介 熊猫眼是一个平时用来学习的练手的项目&#xff0c;做这样一个应用的目的主要有两个&#xff1a; 公司项目因为历史原因还有风险控制方面的问题&#xff0c;新的技术不一定能够应用在现有的版本上。所以手痒了就自己弄个应用写一写&#xff0c;持续的更新增加自己的技能熟…...

为什么要完善网站建设/学seo推广

朋友们&#xff0c;如需转载请标明出处&#xff1a;https://blog.csdn.net/jiangjunshow 声明&#xff1a;在人工智能技术教学期间&#xff0c;不少学生向我提一些python相关的问题&#xff0c;所以为了让同学们掌握更多扩展知识更好的理解人工智能技术&#xff0c;我让助理负…...

网站建设销售好做吗/人民网 疫情

在我们UI设计师在做设计工作的时候&#xff0c;最怕的是什么&#xff1f;那就是不熟悉的场景和业务&#xff0c;那么&#xff0c;今天为大家分享的交互设计师如何做好陌生领域设计&#xff1f;平时工作时公司产品线比较多&#xff0c;可能就会面临做完这个项目接着做下一个项目…...