# 一、概述
在web开发中,经常遇到处理图片文件上传的情况,而在Nodejs中处理图片上传的方式有很多,主要是借助于第三方模块来实现,接下来,我分别介绍如何在express框架和在Koa2框架中实现图片上传。
注意
:若想实现图片上传功能,form表单的enctype属性必须指定为multipart/form-data
<form action="xxx" method="POST" enctype="multipart/form-data">
</form>
# 二、Express框架中实现图片上传
Express中主要借助formidable
模块来实现文件上传,formidable
是一个用于处理文件、图片、视频等数据上传的模块,支持GB级上传数据处理,支持多种客户端数据提交。有极高的测试覆盖率,非常适合在生产环境中使用。
(1)安装
npm i express //安装express
npm i formidable //安装formidable
(2)在项目的根目录下新建upload文件夹,作为图片上传存放的路径
(3)新建server.js文件,代码如下:
const express = require("express");
const formidable = require("formidable");
const path = require('path')
const app = express();
app.use(express.static("./upload")); //开放静态目录
//设置跨域访问
app.all("*", function(req, res, next) {
//设置允许跨域的域名,*代表允许任意域名跨域
res.header("Access-Control-Allow-Origin", "*");
//允许的header类型,*代表允许任意header类型
res.header("Access-Control-Allow-Headers", "*");
//跨域允许的请求方式
res.header("Access-Control-Allow-Methods", "PUT,POST,GET,DELETE,OPTIONS");
if (req.method.toLowerCase() == "options") {
res.send(200); //让options尝试请求快速结束
} else {
next();
}
});
app.post("/upload", (req, res) => {
const form = new formidable.IncomingForm();
form.multiples = false; //是否支持解析多个上传的文件,如果前台允许上传多个图片,可以设置为true,默认为false
form.uploadDir = "./upload"; //配置上传路径
form.keepExtensions = true; //保留原有后缀名
form.maxFieldsSize = 20 * 1024 * 1024; //文件大小,默认为20m
form.parse(req, (err, fields, file) => {
const fileType = file.uploadFile.type
.substring(file.uploadFile.type.lastIndexOf("/") + 1)
.toLowerCase(); //获取图片的后缀名
//判断上传的是否为图片文件
if (!/(gif|jpg|jpeg|png|webp|svg|bmp)$/.test(fileType)) {
res.status(400).json({
code: 400,
msg: "上传的必须为图片文件"
});
} else {
//返回服务器上存放的真实图片路径,在这里本地测试服务器端口为8888,实际项目中填入真实服务器地址即可
const filePath = "http://localhost:8888/" + path.parse(file.uploadFile.path).base
res.status(200).json({
code: 200,
msg: "success",
path: filePath
});
}
});
});
app.listen(8888, () => {
console.log("start...");
});
在VS Code中打开终端或在根目录下打开cmd窗口,运行node server.js
启动服务器
(4)新建html静态页面,用于上传图片,代码如下:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<form action="http://localhost:8888/upload" method="POST" enctype="multipart/form-data">
<input type="file" name="uploadFile" id="upload"><br>
<img id="preview" width="120"><br>
<input type="submit" value="上传">
</form>
<script>
//处理选择图片文件后显示预览图
var upload = document.querySelector('#upload')
var preview = document.querySelector("#preview")
upload.onchange = function () {
var reader = new FileReader()
reader.readAsDataURL(this.files[0])
reader.onload = function () {
preview.src = reader.result
}
}
</script>
</body>
</html>
# 三、koa2框架中实现图片上传
koa2中实现文件上传的模块用的则是koa-body。模块的一些配置如下:
(1)koa-body 的基本参数
参数名 | 描述 | 类型 | 默认值 |
---|---|---|---|
patchNode | 将请求体打到原生 node.js 的ctx.req 中 |
Boolean | false |
patchKoa | 将请求体打到 koa 的 ctx.request 中 |
Boolean | true |
jsonLimit | JSON 数据体的大小限制 | String / Integer | 1mb |
formLimit | 限制表单请求体的大小 | String / Integer | 56kb |
textLimit | 限制 text body 的大小 | String / Integer | 56kb |
encoding | 表单的默认编码 | String | utf-8 |
multipart | 是否支持 multipart-formdate 的表单 |
Boolean | false |
urlencoded | 是否支持 urlencoded 的表单 |
Boolean | true |
text | 是否解析 text/plain 的表单 |
Boolean | true |
json | 是否解析 json 请求体 |
Boolean | true |
jsonStrict | 是否使用 json 严格模式,true 会只处理数组和对象 |
Boolean | true |
formidable |
配置更多的关于 multipart 的选项 |
Object | {} |
onError | 错误处理 | Function | function(){} |
stict | 严格模式,启用后不会解析 GET, HEAD, DELETE 请求 |
Boolean | true |
(2)formidable的相关配置参数
参数名 | 描述 | 类型 | 默认值 |
---|---|---|---|
maxFields | 限制字段的数量 | Integer | 1000 |
maxFieldsSize | 限制字段的最大大小 | Integer | 2 * 1024 * 1024 |
uploadDir | 文件上传的文件夹 | String | os.tmpDir() |
keepExtensions | 保留原来的文件后缀 | Boolean | false |
hash | 如果要计算文件的 hash,则可以选择 md5/sha1 |
String | false |
multipart | 是否支持多文件上传 | Boolean | true |
onFileBegin | 文件上传前的一些设置操作 | Function | function(name,file){} |
(3)安装依赖
npm i koa koa-static koa-body koa-router
(4)根目录下新建upload文件夹,用于存放上传的图片文件
(5)前台代码不变,后台server.js代码如下
const Koa = require("koa");
const static = require("koa-static"); //处理静态资源的访问
const Body = require("koa-body");
const path = require("path");
const Router = require("koa-router");
const app = new Koa();
const router = new Router();
app.use(async (ctx, next) => {
//允许来自所有域名请求(不携带cookie请求可以用*,如果有携带cookie请求必须指定域名)
ctx.set("Access-Control-Allow-Origin", "*");
// 设置所允许的HTTP请求方法
ctx.set("Access-Control-Allow-Methods", "OPTIONS, GET, PUT, POST, DELETE");
//允许的header类型,*代表允许任意header类型
ctx.set("Access-Control-Allow-Headers", "*");
if (ctx.method == "OPTIONS") {
ctx.body = "";
ctx.status = 200;
} else {
await next();
}
});
app.use(
Body({
multipart: true, //支持文件上传
formidable: {
uploadDir: path.join(__dirname, "./upload"), //设置上传的文件路径
keepExtensions: true, //保持原有扩展名
maxFileSize: 20 * 1024 * 1024 //文件上传大小,20M
}
})
);
app.use(static(__dirname + "/upload")); //开放静态目录
router.post("/upload", async (ctx) => {
const fileType = ctx.request.files.uploadFile.type
.substring(ctx.request.files.uploadFile.type.lastIndexOf("/") + 1)
.toLowerCase(); //获取图片的后缀名
//判断上传的是否为图片文件
if (!/(gif|jpg|jpeg|png|webp|svg|bmp)$/.test(fileType)) {
ctx.status = 400
ctx.body = {
code: 400,
msg: "上传的必须为图片文件"
}
} else {
//返回服务器上存放的真实图片路径,在这里本地测试服务器端口为8888,实际项目中填入真实服务器地址即可
const filePath = "http://localhost:8888/" + path.parse(ctx.request.files.uploadFile.path).base
ctx.body = {
code: 200,
msg: "success",
path: filePath
}
}
});
app.use(router.routes()).use(router.allowedMethods());
app.listen(8888, () => {
console.log("start...");
});