您的位置:首页 > Web前端 > Node.js

前台使用ajax上传图片,后台 node.js 使用 formidable 进行图片接受并存于服务器静态文件夹中

2018-03-24 23:26 1501 查看
相信现在很多小伙伴在使用node来搭建后台,那么前后台对接少不了的就是图片的上传,下面我将通过这篇文章来对图片上传问题进行详细的介绍:

本项目源码已经上传GitHub,https://github.com/crazyJiaLin/node-img-upload-demo

首先,我们需要一些准备:

通过node+express搭建后台服务器,并配置静态资源文件路径,具体配置方式网上有很多种解法,这里不再展示,如果不想自己搭建,可以从本人GitHub中检出直接使用;

搭建MVC(model+view+controller)目录结构如下图:



除express+ejs,我们还需要安装一些模块

$ npm install formidable dateformat -S


接着,我们建立上传图片的模块,即文件目录中的model/upload-model.js

var path = require('path');
var fs = require('fs');                     //文件系统
var formidable = require('formidable');     //引用formidable来解析请求,上传文件
var dateFormat = require('dateformat');     //生成时间对象,来重命名上传的图片,避免图片的重复

module.exports = {
/**通过formdata上传图片
* 参数1--req,express请求
* 参数2--dirName,静态资源下的路径
* 参数3--callback,回调函数,callback(err,fields,uploadPath),返回错误对象,表单字段和图片上传的地址
*/
uploadPhoto : function(req,dirName,callback){
//上传文件
// parse a file upload
var form = new formidable.IncomingForm();
form.uploadDir = path.join(__dirname,'../static',dirName);
//保留文件扩展名
form.keepExtensions = true;
form.encoding = 'utf-8';

form.onPart = function(part) {
if (part.filename != '') {
// let formidable handle all non-file parts
form.handlePart(part);
}
};
//通过formidable进行图片的上传
form.parse(req, function(err, fields, files) {
if(err) {
callback && callback(err,null,null);
return;
}
if(!files.userfile){    //前台上传表单的时候,文件使用的字段名是userfile,这里对文件是否为空进行判断
var errMsg = {
errCode : -10,
errMsg : '文件为空'
};
callback && callback(errMsg,null,null);
return;
}

//文件不为空的情况下,说明文件已经上传到我们的服务器中
//这时,需要我们使用fs模块把我们已经上传的路径改为我们想要的位置
//并且使用dateFormat来创建时间字符串,从而避免文件的重名
var time = dateFormat(new Date(), "yyyymmddHHMMss");
//files.userfile.path代表的是formidable为我们上传文件后绝对路径,通过path的extname来获取图片后缀
var extName = path.extname(files.userfile.path);
var newName = time + '_' + Math.floor(Math.random()*9999) + extName;    //使用dateFormat+随机数+文件后缀生成新文件名

var oldPath = files.userfile.path;
var newPath = path.join(__dirname,'../static',dirName, newName);
//修改文件的名字
fs.renameSync(oldPath,newPath);
var finalPath = path.join('/',dirName,newName).split('\\').join('/');   //将路径中的'\'替换为'/'
callback && callback(null, fields, finalPath);  //回掉函数返回表单字段以及图片上传的相对路径
});
}
};


然后创建controller层img-upload.js文件,来接受请求,然后交接到model层

var express = require('express');
var router = express.Router();
var uploadModel = require('./../model/upload-model');//上传model

router.post('/imgUpload',function(req,res){
/**设置响应头允许ajax跨域访问**/
res.setHeader("Access-Control-Allow-Origin","*");
uploadModel.uploadPhoto(req,'img',function(err,fields,uploadPath){
if(err){
return res.json({
errCode : 0,
errMsg : '上传图片错误'
});
}
console.log(fields);    //表单中字段信息
console.log(uploadPath);    //上传图片的相对路径
res.json({
errCode : 1,
errMsg : '上传成功',
fields :  fields,
uploadPath : uploadPath
});
});
});

module.exports = router;


这里记得将我们的路由配置放置到server.js中,并使用node server.js 启动项目后台

//路由配置
var imgUploade = require('./controller/img-upload');
app.use(imgUploade);


然后,我们就可以在前台创建表单对象来提交请求了(index.html)

<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>图片上传demo</title>
</head>
<body>

<input type="file" id="img-upload">
<button id="submit-button">开始上传</button>

<script src="./js/jquery-3.1.0.min.js"></script>
<script>
$('#submit-button').on('click',function(){
var myPhoto = $('#img-upload')[0].files[0];
var oMyForm = new FormData();
oMyForm.append("name", 'crazyJiaLin');
oMyForm.append("userfile", myPhoto);
$.ajax({
type : 'POST',
url : '/imgUpload',
cache : false,  //不需要缓存
processData : false,    //不需要进行数据转换
contentType : false, //默认数据传输方式是application,改为false,编程multipart
data : oMyForm,
dataType : 'json'
}).done(function(data){
console.log(data);
alert(data.errMsg);
}).fail(function(err){
console.error(err);
});
});
</script>
</body>
</html>


下面来展示一下上传效果:

选择文件后,点击上传按钮,返回上传成功数据



后台返回数据以及文件中图片内容





感谢大家支持,源码已经上传GitHub,https://github.com/crazyJiaLin/node-img-upload-demo,望多多支持!
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签: