一、使用FormData和formidable实现二进制文件(图片)的上传
1、FormData对象
能够处理页面中的表单数据,使用new关键字实例化FormData()构造函数来创建FormData对象。
var formData = new FormData(form);
FormData()构造函数接受form表单对象作为参数。它表示将普通的form表单对象转换为FormData对象。
FormData对象提供了处理表单数据的方法,不需要拼接表单数据字符串的繁琐工作,使用起来非常方便。
(1)set('key', 'value'):第1个参数表示FormData对象的属性名;第2个参数表示该属性名的属性值。
(2)get('key'):?接收1个参数表示FormData对象的属性名。
(3)append('key', 'value'):第1个参数表示FormData对象的属性名;第2个参数表示该属性名的属性值
(4)delete('key'):接收1个参数表示FormData对象的属性名
? 2、formidable表单解析对象
能够将FormData对象解析成表单数据。FormData对象可以作为POST请求参数直接传递给服务器端。服务器端使用formidable表单解析对象的parse()方法处理FormData对象,并将FormData对象数据的处理结果返回给客户端。
formidable是一个第三方模块,用于将FormData对象解析成表单数据,从而实现表单数据的处理和文件的上传。
(1)安装:npm install formidable
(2)使用:
const formidable = require('formidable')
const form = new formidable.IncomingForm()
(3)常用属性:
keepExtensions:用来设置上传的二进制文件是否保持原来文件的扩展名,默认值为false表示不保持。如果设置keepExtensions属性的值为true表示保持。
uploadDir:用来设置上传文件存放的文件目录,默认是系统的临时目录。
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>图片上传</title>
<script src="../js/jquery-3.4.1.js"></script>
</head>
<body style="text-align: center;">
<label>请选择文件:</label>
<input type="file" id="file"> <!-- 文件选择的标签 -->
<br><br>
<div id='box'></div> <!-- 显示用户上传的图片 -->
<script>
$(function(){
//给input标签绑定change事件
$('#file').change(function(){
//获取input的value
let fileName = $('#file').val()
console.log(fileName)
//获取上传文件的扩展名
let extName = fileName.substring(fileName.lastIndexOf('.'),fileName.length).toLowerCase();
if (extName==='.png' || extName==='.jpg') {
//创建FormData对象
let formData = new FormData();
//将上传的文件信息保存到formData中
formData.append('upload',$('#file')[0].files[0])
//向服务器发起请求,上传文件
$.ajax({
url: 'http://localhost:3000/upload/images',
type: 'post',
data: formData,
cache: false, //取消缓存
contentType: false, //必须的
processData: false, //必须的
success: function(result){
//创建img标签
let img = document.createElement('img');
//设置img标签的样式:width、height
img.style.width = 300 + 'px';
img.style.height = 200 + 'px';
//设置img标签的src
img.src = result.path
//img.src = http://localhost:3000/images/uploads/2.png
//将img标签添加到div中
$('img').remove()
$('#box').append(img);
},
error: function(err){
console.log(err)
}
})
}else{
alert('只支持png和jpg格式的图片')
}
})
})
</script>
</body>
</html>
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Document</title>
</head>
<body style="text-align: center;">
<form action="http://localhost:3000/upload/middleware" method="post" enctype="multipart/form-data">
<input type="file" name="photo">
<button type="submit">上传</button>
</form>
</body>
</html>
const express = require('express');
const fs = require('fs');
const path = require('path');
const formidable = require('formidable');
const router = express.Router();
const multiparty = require('connect-multiparty');
const multipartMiddleware = multiparty();//创建上传中间件
/*
上传接口:http://localhost:3000/upload/images
*/
router.post('/images',(req, res) => {
//1.创建上传文件的保存目录
let cacheFolder = 'public/images/uploads'
if(!fs.existsSync(cacheFolder)){ //若上传目录不存在则创建
fs.mkdirSync(cacheFolder);
}
//2.创建formidable的实例,用于解析FormData的数据
let form = new formidable.IncomingForm();
form.encoding = 'utf-8' //设置编码格式
form.uploadDir = cacheFolder //指定上传路径
form.keepExtensions = true //保留上传文件的后缀名
form.maxFieldsSize = 2*1024*1024 //设置上传文件的大小为2M
form.type = true //表单类型
//3.解析上传数据:使用parse方法
let displayUrl; //用于保存上传文件在服务器端的存储路径
form.parse(req,function (err,fields,files) {
/*
err: 上传失败后的异常信息
fields: 表单中所有字段(控件)
files:上传的文件
*/
if(err){
res.send(err)
return
}
let extName = ''
switch (files.upload.mimetype) {
case 'image/jpeg':
extName = 'jpg'
break;
case 'image/jpg':
extName = 'jpg'
break;
case 'image/png':
extName = 'png'
break;
}
if (extName.length === 0){ //上传文件的类型错误
res.send({
code: 202,
msg: '只支持png和jpg格式的图片'
})
return
}else{
//3.1 将上传的路径和上传文件的名称进行拼接(originalFilename表示上传文件的原名)
let newPath = form.uploadDir + '/'+ files.upload.originalFilename
//3.2 重命名上传文件
//console.log('上传的原始路径:',files.upload)
fs.renameSync(files.upload.filepath,newPath)
//3.3 拼接响应给客户端的上传文件的路径
displayUrl= `http://localhost:3000/images/uploads/${files.upload.originalFilename}`
res.send({
code: 200,
path: displayUrl
})
}
})
});
/*
利用上传中间件进行上传:http://localhost:3000/upload/middleware
*/
router.post('/middleware',multipartMiddleware,(req, res) => {
//1.获取上传文件
let file = req.files.photo
//2.创建上传文件的存放路径
let desc_path = path.join(__dirname,'../public/images/uploads')+"\\"+file.originalFilename
console.log(file.path)
fs.readFile(file.path,function (err,data){
fs.writeFile(desc_path,data,function (err) {
if (err){
console.log(err)
res.send({
code: 202,
msg: '上传失败'
})
}
})
})
let imgPath = 'http://localhost:3000/images/uploads/'+file.originalFilename
res.send({
code: 200,
path: imgPath
})
})
module.exports = router;
|