好久没有更新博客了,这几天在写文件上传的时候遇到了一个新的问题,就是关于ajax实现文件上传的问题
这几天在做一个小的demo,类似于论坛的一个东西,基于jquery+express+mongo的一个小的案例,在做到关于设置个人头像的时候,有这样一个场景,用户可以上传头像,然后上传头像成功后,可以对原图进行剪裁,最后的到剪裁后的图像,更改成用户头像。
其实,这个技术上有很多种解决方案,我的问题不是在于实现这个功能的问题上,功能很好实现关键在于用户体验,功能实现的话,图省事,我可以直接用form表单将用户上传的头像提交到后台,后台先存储图片,然后跳转到例外一个页面,将用户上传的图片进行剪裁,这样做很简单,但是这里有个明显的弊端,就是重新刷新了页面,跳转到另外一个页面了,这样用户体验会很不好,所以我就想能不能异步提交表单。
别说,还真有可以异步提交表单的方法,我之前也听说过,但是一直没有用过,在这里,针对这个场景,两种解决的方法,第一个是formData,第二个是ajaxForm插件,我引用的是第一个解决方法,用formData对象来解决异步提交表单的问题,formData是h5中新增的一个js的对象,兼容主流浏览器(别跟我说IE678,),如果考虑低版本浏览器的话,那么还是考虑表单直接提交吧(体验什么就不要考虑了),或者可以用下ajaxForm(基于jquery插件)。
别说了,说的太累了,直接上代码吧
前台html代码(基于bootstrap的)
File input
上传
上传成功
前台js
$('#upfile_btn').click(function(event) {
var formData = new FormData();
formData.append('file', $('#file')[0].files[0]);
$.ajax({
url: '/upavatar',
type: 'POST',
cache: false,
data: formData,
processData: false,
contentType: false
}).done(function(data) {
if (data.status == '1') {
//成功
$('#cg').fadeIn().fadeOut(4000, function() {
var htmlStr = '建材';
$('.jiancaidiv').append(htmlStr);
$('#element_id').Jcrop();
$('#jiancai').click(function(event) {
// alert(111)
/* Act on the event */
var width = parseInt($(".jcrop-holder div:first").css('width'));
var height = parseInt($(".jcrop-holder div:first").css('height'));
var left = parseInt($(".jcrop-holder div:first").css('left'));
var top = parseInt($(".jcrop-holder div:first").css('top'));
console.log(width + ' ' + ' ' + height + ' ' + left + ' ' + top);
$.ajax({
url: '/docut',
type: 'POST',
dataType: 'json',
data: {
width: width,
height: height,
left: left,
top: top,
},
})
.done(function(data) {
if (data.status == '1') {
alert('修改头像成功');
location.href = '/'
}
})
.fail(function() {
console.log("error");
})
.always(function() {
console.log("complete");
});
});
});
} else {
//失败
}
console.log('success');
}).fail(function(res) {});
});
后台node(js代码)
var express = require('./node_modules/express');
var bodyParser = require('body-parser');
var router = require('./route.js');
var session = require('express-session');
var formidable = require("formidable");
var fs = require('fs');
var gm = require('./node_modules/gm')
var db = require('./models/db.js');
// create application/x-www-form-urlencoded parser
var urlencodedParser = bodyParser.urlencoded({
extended: false
});
var app = express();
//使用session
app.use(session({
secret: 'keyboard cat',
resave: false,
saveUninitialized: true
}));
//创建静态服务
app.use(express.static('./public'));
//上传头像部分
app.post('/upavatar', function(req, res) {
var form = new formidable.IncomingForm();
form.uploadDir = "./avatar";
form.parse(req, function(err, fields, files) {
console.log(files);
var oldPath = './' + files.file.path;
var newPath = './avatar/' + req.session.userName + '.jpg';
fs.rename(oldPath, newPath, function(err) {
if (err) {
//上传失败
var json = {
'status': '0'
};
res.send(json);
} else {
//成功
var json = {
'status': '1',
'userName': req.session.userName
};
res.send(json);
}
})
});
})
app.post('/docut', urlencodedParser, function(req, res) {
console.log(req.body);
var width = req.body.width;
var height = req.body.height;
var left = req.body.left;
var top = req.body.top;
gm("./avatar/" + req.session.userName+'.jpg')
.crop(width, height, left, top)
.write("./avatar/" + req.session.userName+'.jpg', function(err) {
if (err) {
var json = {'status':'-1'};
res.send(json);
return;
}
var json = {'status':'1'};
res.send(json);
});
})
这里前台将图片上传后,前台首先将文件对象放到formData对象中,然后以ajax的方式提交后台,后台通过formidable接受到文件,将图片保存到avatar文件夹下并且改名,之后前台在当前以页面显示图片,给用户剪裁,剪裁好后,将剪裁的参数提交到后台,后台根据参数用gm剪裁,保存更改