一、使用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:用来设置上传文件存放的文件目录,默认是系统的临时目录。
3、上传示例:
(1)前端页面:
<label>请选择文件:</label>
<input type="file" id="file">
<div id="box"></div>
<script>
$(function () {
$('#file').change(function () {
if($('#file').val().length){
let fileName = $('#file').val();
let extension = fileName.substring(fileName.lastIndexOf('.'),fileName.length).toLowerCase();
if(extension == '.jpg' || extension =='.png'){
let formData = new FormData();// 创建空的formData表单对象
formData.append('upload',$('#file')[0].files[0]); //将用户选择的文件追加到formData表单对象中
$.ajax({
url: 'http://localhost:3000/users/upload',
type: 'post',
data: formData,
cache: false,
contentType: false, //不可缺参数
processData: false, //不可缺参数
success: function(result) {
let img = document.createElement('img');
img.style.width = 300+'px';
img.style.height = 200+'px'
img.src = result.path;
$('img').remove() //删除前一次的img元素
$('#box').append(img)
},
error: function(err){
console.log(err)
}
})
}else{
alert('只支持png和jpg格式图片')
}
}
})
})
</script>
(2)后台接口:
var express = require('express');
var formidable = require('formidable')
var fs = require('fs');
var router = express.Router();
/*
http://localhost:3000/users/upload
*/
router.post('/upload',(req, res) => {
let cacheFolder = 'public/images/uploads'
if(!fs.existsSync(cacheFolder)){
fs.mkdirSync(cacheFolder)
}
let form = new formidable.IncomingForm();
form.encoding = 'utf-8'; //设置编辑
form.uploadDir = cacheFolder; //设置上传目录
form.keepExtensions = true; //保留后缀
form.maxFieldsSize = 2 * 1024 * 1024; //文件大小
form.type = true;
let displayUrl;
form.parse(req,function (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;
}
console.log(extName)
if (extName.length === 0){
res.send({
code: 202,
msg: '只支持png和jpg格式图片'
})
return
}else{
let newPath = form.uploadDir + '/' + files.upload.originalFilename;
displayUrl = `http://localhost:3000/images/uploads/${files.upload.originalFilename}`
console.log("====>",newPath);
fs.renameSync(files.upload.filepath,newPath);
res.send({
code: 200,
path: displayUrl
})
}
})
})
module.exports = router;
二、通过form + connect-multiparty表单上传图片
1、前端页面:
<form action="http://localhost:3000/users/upload_test" method="post" enctype="multipart/form-data">
<input type="file" name="photo">
<button type="submit">提交</button>
</form>
2、后台接口:
//使用上传中间件,需要安装:npm install connect-multiparty
const multiparty = require('connect-multiparty');
const multipartMiddleware = multiparty();
/*
http://localhost:3000/users/upload_test
*/
router.post('/upload_test',multipartMiddleware,(req,res)=>{
console.log("上传文件名:",req.files.photo)
//上传图片参数
var file = req.files.photo;
//定义上传文件的存放路径
var des_file = path.join(__dirname,'../public/images/uploads')+"\\"+file.originalFilename
console.log(des_file) //上传路径:des_file
console.log(file.path) //临时文件路径:file.path
//将文件存入本地服务器文件中
fs.readFile(file.path,function (err,data){
fs.writeFile(des_file,data,function(err){
if(err){
console.log(err)
res.json({code:1});
return
}
})
})
//网络访问时public目录不能出现,public是虚拟目录
let imgpath = `http://localhost:8089/images/${file.originalFilename}`;
//将图片存放的地址返回
res.send( {
code: 0,
path: imgpath
})
})
三、ajax + multiparty实现图片上传
注意:在客户端提交的时候,html页面form 表单要加入 enctype="multipart/form-data"
但是 ajax 不需要加入
1、前端页面
<input type="file" name="images" onchange="fileUpload(this)">
<button onclick="uploadPictures()">上传图片</button>
<!--获取服务返回图片数据-->
<div>
<img class="img" src="" alt="">
</div>
<script>
var fileImg;
//读取图片
function fileUpload(_this) {
var fileReader = new FileReader();//创建文件读取对象
fileImg = _this.files[0];//获取file组件中的文件
}
//上传图片
function uploadPictures() {
var formData = new FormData();
//图片
if (fileImg != null) {
formData.append("image", fileImg);
}
$.ajax({
url: 'http://localhost:3000/users/uploading',
type: 'post',
data: formData,
processData: false,
contentType: false,
success: function (res) {
$('.img').attr('src', res.path);
},
error: function (err) {
console.log(err);
}
});
}
</script>
2、后台接口
/*
http://localhost:3000/users/uploading
*/
router.post('/uploading',(req, res) => {
var form = new multiparty.Form();
form.uploadDir='public/images/uploads'; //上传图片保存的地址(目录必须存在)
form.parse(req, function(err, fields, files) {// 1、fields:获取表单的数据 2、files:图片上传成功返回的信息
let newPath = form.uploadDir + '/' + files.image[0].originalFilename;
fs.renameSync(files.image[0].path,newPath);
let imgUrl = 'http://localhost:3000/images/uploads/' + files.image[0].originalFilename;
res.send({
path: imgUrl
})
})
})