“Node.js® is a JavaScript runtime built on Chrome's V8 JavaScript engine”官网的一句介绍大致是说“Node.js 是一个基于 Chrome V8 引擎的 JavaScript 运行时”,简单来说就是一个能让JS运行在服务端的环境。
前言
最近公司事比较多,有点耽搁了,但依旧坚持着周更,不管写得如何,不放弃继续努力~
今天主题讲点有用的,前端上传文件应该是个比较常见的事情了,那么后端要如何接收呢?今天就来玩玩这个事情吧。
Node.js 提供一组类似 UNIX(POSIX)标准的文件操作API。(这句话可不是我说的,官方话语,反正其实就是让我们学习fs模块就对了,管那么多。。。)
相关API罗列
Node中和文件系统相关的API基本都有其同步与异步方法对应。
文件-读与写
既然是对文件的操作,那我们先来聊聊对一个已存在的文件的读写操作吧,话不多说,直接上代码,太 easy 了,多说你们又说我划水了。
我们创建 1.txt 文件
Hello, World.
你好, 世界.
创建 test.js 文件
const fs = require('fs');
fs.readFile('./1.txt', 'utf8', (err, data) => {
console.log(data); // Hello, World 你好, 世界
});
在cmd中执行 node test.js
我们就简单的读取到了一个文件了, 如此简单就不必多说了,我们接下来往这个 1.txt 文件写入东西吧。
我们稍微修改一下 test.js的代码
const fs = require('fs');
fs.writeFile('./1.txt', '我是写入的数据', err => {
if(err) {
console.log('读取文件失败')
}else {
console.log('写入成功') // 写入成功
}
})
再次执行node test.js
查看 1.txt 文件
同步方法:
// 同步写入文件
var str = '我是写进来的';
fs.writeFileSync('./1.txt', '我是写入的数据', err => {
console.log('写入文件失败') // 错误回调
})
// 同步读取文件
try{
var data = fs.readFileSync('./1.txt', 'utf-8');
console.log(data)
}catch (e) {
console.log('读取文件失败')
}
文件-内容追加
细心的铁子可能发现了,我们在给文件写入数据的时候,是以覆盖的形式写入的,那么如何用追加的形式的,Node自然也是提供了相关API了。
再改 test.js 文件
const fs = require('fs');
fs.appendFile('./1.txt', '*** 我是追加进来的数据 ***', err => {
if(err) console.log('追加数据失败')
})
查看 1.txt 文件
同步方法:
const fs = require('fs');
fs.appendFileSync('./1.txt', '*** 我是追加进来的数据 ***')
文件-创建
Node并没有直接提供创建文件的相关API,我们能直接利用写入的API来完成,默认写入的API如果所填写的文件不存在,则会帮忙创建
const fs = require('fs');
fs.writeFile('./111.txt', '我是写入的数据', err => {
if(err) {
console.log('读取文件失败')
}else {
console.log('写入成功') // 写入成功
}
})
文件-删除
const fs = require('fs');
fs.unlink('./1.txt', err => {
if(err) console.log('删除文件失败')
})
同步方法:
const fs = require('fs');
fs.unlinkSync('./1.txt')
目录-创建
如果是已经存在的目录,不会重复创建
const fs = require('fs');
fs.mkdir('./public', err => {
if(err) console.log('创建目录失败')
})
同步方法:
const fs = require('fs');
fs.mkdirSync('./public')
目录-读取
我们在 public 目录下新建 2.txt 文件与 newPublic 目录
const fs = require('fs');
fs.readdir('./public', (err, files) => {
console.log(files); // [ '2.txt', 'newPublic' ]
})
同步方法:
const fs = require('fs');
console.log(fs.readdirSync('./public')); // [ '2.txt', 'newPublic' ]
目录-删除
目录下有文件/目录的话无法删除,只能删除空目录
const fs = require('fs');
fs.rmdir('./public', err => {
if(err) console.log('删除目录失败')
})
同步方法:
const fs = require('fs');
fs.rmdirSync('./public')
文件/目录-获取信息
const fs = require('fs');
fs.stat('./1.txt', (err, stats) => {
if (err) {
return console.log('获取文件信息失败');
}
console.log(stats);
console.log("是否为一个文件:" + stats.isFile());
console.log("是否为一个目录:" + stats.isDirectory());
});
方法 | 描述 | stats.isFile() | 如果是文件返回 true,否则返回 false。 | stats.isDirectory() | 如果是目录返回 true,否则返回 false。 | stats.isBlockDevice() | 如果是块设备返回 true,否则返回 false。 | stats.isCharacterDevice() | 如果是字符设备返回 true,否则返回 false。 | stats.isSymbolicLink() | 如果是软链接返回 true,否则返回 false。 | stats.isFIFO() | 如果是FIFO,返回true,否则返回 false。FIFO是UNIX中的一种特殊类型的命令管道。 | stats.isSocket() | 如果是 Socket 返回 true,否则返回 false。 |
---|
同步方法:
const fs = require('fs');
const stat = fs.statSync('./1.txt')
console.log(stat)
文件/目录-是否存在
const fs = require('fs');
fs.exists('./1.txt', res => {
console.log('文件/目录存在:' + res); // 文件/目录存在:true
})
同步方法:
console.log('文件/目录存在:' + fs.existsSync('./1.txt')); // 文件/目录存在:true
文件/目录-重命名与移动
我们直接给文件/目录改名字
const fs = require('fs');
fs.rename('./1.txt', './2.txt', err => {
console.log(err)
})
fs.rename('./public', './newPublic', err => {
console.log(err)
})
也可以利用该API实现文件位置的移动
fs.rename('./2.txt', './public/1.txt', err => {
console.log(err)
})
同步方法:
const fs = require('fs');
fs.renameSync('./public/1.txt', './2.txt') // 我们把文件移动回来
接收前端的上传的图片
我们简单来实现一下前端上传图片(FormData形式)的时候,原生Node是需要如何来处理的。
- 新建index.html
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>文件上传</title>
</head>
<script src="https://apps.bdimg.com/libs/jquery/2.1.4/jquery.min.js"></script>
<body>
<input type="file" id="file" name="myfile" />
<button>点击</button>
<script>
$("button").click(() => {
var file = document.getElementById("file").files[0];
var form = new FormData();
form.append("file", file);
form.append('username', 'username');
form.append('password', 'password');
$.ajax({
url: 'http://localhost:8888',
type: "POST",
data: form,
async: false, //异步
processData: false, // 让jq不对formData对象进行处理
contentType: false, // 自动加上对应的contentType
success: (result) => {
console.log(result)
}
});
});
</script>
</body>
</html>
- 服务端处理
const fs = require('fs');
const http = require('http');
http.createServer((req, res) =>{
// 允许跨域(不急, 后面跨域会专门来说)
res.setHeader("Access-Control-Allow-Origin", "*");
res.setHeader("Access-Control-Allow-Headers", "Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild");
res.setHeader("Access-Control-Allow-Methods","PUT,POST,GET,DELETE,OPTIONS");
res.setHeader("X-Powered-By","3.2.1");
res.setHeader("Content-Type", "application/json;charset=utf-8");
let chunks = [];
let size = 0;
let buffer = null;
let offsets = [];
req.on('data', (chunk) => {
// chunk默认为一个二进制数据流, 该方法会执行多次, 需要我们手动累加二进制数据
chunks.push(chunk);
size = chunk.length; // 获取相关Buffer流的大小
});
req.on('end',() => {
// 合并相关Buffer流
buffer = Buffer.concat(chunks, size);
for(let i = 0;i < buffer.length; i++){
if(buffer[i].toString() == 13 && buffer[i+1].toString() == 10){
offsets.push(i);
}
}
// 获取文件名
let name = buffer.slice(offsets[0], offsets[1]).toString().split(';')[2].split('=')[1];
let filename = name.split("\"");
// 写出文件
let data = buffer.slice(offsets[3] + 2, offsets[offsets.length - 2]);
fs.writeFileSync('./' + filename[1], data);
});
res.end('文件上传成功');
}).listen('8888');
console.log('Server running at http://localhost:8888');
执行后的结果,当前目录下就有上传的图片了。。。nice
- 关于Buffer类型,在JavaScript语言自身只有字符串数据类型, 没有二进制数据类型。但在处理像TCP流或文件流时,必须使用到二进制数据。因此在Node中,定义了一个Buffer类,该类用来创建一个专门存放二进制数据的缓存区。 www.runoob.com/nodejs/node…
- 关于offsets偏移量,我们把buffer流toString()打印一下,在控制台大概能看到一大堆乱七八糟的东西,但是我们真正要取的只有 PNG 下面那部分,所以需要搞点偏移量,取到图片就行。包括文件的名字也能从中获取。
- 最后说一下,其实Node来处理文件上传已经有很多npm包能快速、方便的上传了,这里简单讲一下,就是希望对这其中有个大概的了解,就这样子吧,嘿嘿~
常见问题FAQ
- 免费下载或者VIP会员专享资源能否直接商用?
- 本站所有资源版权均属于原作者所有,这里所提供资源均只能用于参考学习用,请勿直接商用。若由于商用引起版权纠纷,一切责任均由使用者承担。更多说明请参考 VIP介绍。
- 提示下载完但解压或打开不了?
- 找不到素材资源介绍文章里的示例图片?
- 模板不会安装或需要功能定制以及二次开发?
发表评论
还没有评论,快来抢沙发吧!