1 前端上传采用 webuploader 上传插件 http://fex.baidu.com/webuploader/getting-started.html
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8" />
<title>1</title>
<link rel="stylesheet" href="webuploader-0.1.5/webuploader.css" />
<script src="js/jquery.js"></script>
<script src="webuploader-0.1.5/webuploader.js"></script>
<style>
#uploader { width: 1000px; height: 400px; border:1px solid black;}
#uploader>div { width: 150px; height: 150px; border:1px solid black; float: left; }
#uploader>div>div{ width: 100%; height: 100%;}
#uploader>div>div img { width: 100%; padding: 0;margin:0;}
#uploader>.img_0 { width: 300px; height: 300px; border:1px solid black;}
.thumbnail { position: relative; }
.thumbnail .error { color: #fff; width: 100%; position: absolute; bottom: 0; background: cornflowerblue; text-align: center; }
</style>
</head>
<body>
<div id="filePicker">选择图片</div>
<div id="uploader">
<div class="img_0"></div>
<div class="img_1"></div>
<div class="img_2"></div>
<div class="img_3"></div>
<div class="img_4"></div>
</div>
</body>
<script>
// 初始化Web Uploader
var uploader = WebUploader.create({
dnd:'#uploader',//启用拖拽容器
auto: true, // 选完文件后,是否自动上传。
swf: 'webuploader-0.1.5/Uploader.swf', // swf文件路径
server: '/upload',// 文件接收服务端。
pick: '#filePicker', // 内部根据当前运行是创建,可能是input元素,也可能是flash.选择文件的按钮。可选。
accept: { // 只允许选择图片文件。
title: 'Images',
extensions: 'gif,jpg,jpeg,bmp,png',
mimeTypes: 'image/*'
},
chunked: true, // 开起分片上传。
//配置生成缩略图的选项。
thumb:{
width: 300,//此次和下面设置一致
height: 300,
// 图片质量,只有type为`image/jpeg`的时候才有效。
quality: 100,
// 是否允许放大,如果想要生成小图的时候不失真,此选项应该设置为false.
allowMagnify: true,
// 是否允许裁剪。
crop: true,
// 为空的话则保留原有图片格式。
// 否则强制转换成指定的类型。
type: 'image/jpeg'
},
//配置压缩的图片的选项
compress:{
width: 600, //jpg图压缩后的尺寸
height: 600,
// 图片质量,只有type为`image/jpeg`的时候才有效。
quality: 90,
// 是否允许放大,如果想要生成小图的时候不失真,此选项应该设置为false.
allowMagnify: false,
// 是否允许裁剪。
crop: false,
// 是否保留头部meta信息。
preserveHeaders: true,
// 如果发现压缩后文件大小比原来还大,则使用原来图片
// 此属性可能会影响图片自动纠正功能
noCompressIfLarger: false,
// 单位字节,如果图片大小小于此值,不会采用压缩。
compressSize: 0
},
formData:{
'a':1
},
method:'POST',
fileNumLimit:5, //验证文件总数量, 超出则不允许加入队列。
fileSizeLimit:undefined, //验证文件总大小是否超出限制, 超出则不允许加入队列。
fileSingleSizeLimit:undefined, //验证单个文件大小是否超出限制, 超出则不允许加入队列,
name:'fileName'
});
// 当有文件添加进来的时候
var i = 0;
uploader.on( 'fileQueued', function( file ) {
var list = $(
'<div id="' + file.id + '" class="thumbnail">' +
'<img>' +
"<span class='delete-icon'>删除</span>"+
'</div>'
);
var img = list.find('img');
$("#uploader>div").eq(i).append( list );
i++;
$("#" + file.id + " .delete-icon").bind("click", function () {
uploader.removeFile(file, true);
$("#" + file.id).remove();
});
//缩略图
uploader.makeThumb( file, function( error, src ) {
if ( error ) {
img.replaceWith('<span>不能预览</span>');
return;
}
// console.log(file)
img.attr( 'src', src );
});
console.log(uploader.getFiles());
console.log(uploader.getFile(file.id));
});
// 文件上传过程中创建进度条实时显示。
uploader.on( 'uploadProgress', function( file, percentage ) {
var list = $( '#'+file.id );
var percent = list.find('.progress span');
// 避免重复创建
if ( !percent.length ) {
percent = $('<p class="progress"><span></span></p>')
.appendTo( list )
.find('span');
}
percent.css( 'width', percentage * 100 + '%' );
});
// 文件上传成功,给item添加成功class, 用样式标记上传成功。
uploader.on( 'uploadSuccess', function( file,response ) {
// console.log(response);//返回的数据
$( '#'+file.id ).addClass('upload-state-done');
});
// 文件上传失败,显示上传出错。
uploader.on( 'uploadError', function( file ) {
var list = $( '#'+file.id );
var error = list.find('div.error');
// 避免重复创建
if ( !error.length ) {
error = $('<div class="error"></div>').appendTo( list );
}
error.text('上传失败');
});
// 不管成功或者失败,文件上传完成时触发,先删除进度条。
uploader.on( 'uploadComplete', function( file ) {
$( '#'+file.id ).find('.progress').remove();
});
</script>
</html>
2 服务器上传采用 formidable 中间件 https://www.npmjs.com/package/formidable,上传涉及到跨域访问 ,添加App.all('*',function (req, res, next){},或添加express跨域中间件 cors https://www.npmjs.com/package/cors
var Express = require('express');
var App = Express();
var Path = require('path');
var Formidable = require('formidable');
var FS = require('fs');
App.use(Express.static(Path.join(__dirname, 'public')));
App.use(Express.static(Path.join(__dirname, 'uploads')));
//allow custom header and CORS
App.all('*',function (req, res, next) {
res.header('Access-Control-Allow-Origin', '*');
res.header('Access-Control-Allow-Headers', 'Content-Type, Content-Length, Authorization, Accept, X-Requested-With , yourHeaderFeild');
res.header('Access-Control-Allow-Methods', 'PUT, POST, GET, DELETE, OPTIONS');
next();
});
App.post('/upload', function(req, res){
// create an incoming form object
var form = new Formidable.IncomingForm();
// specify that we want to allow the user to upload multiple files in a single request
form.multiples = true;
// store all uploads in the /uploads directory
form.uploadDir = Path.join(__dirname, '/uploads');
var images = new Array();
// every time a file has been uploaded successfully,
// rename it to it's orignal name
form.on('file', function(field, file) {
var newName = Date.now() + "_" + file.name;
FS.rename(file.path, Path.join(form.uploadDir,newName),function(err) {
if(err){
throw err;
}
});
images.push(newName);
});
// log any errors that occur
form.on('error', function(err) {
console.log('An error has occured: \n' + err);
});
// once all the files have been uploaded, send a response to the client
form.on('end', function() {
res.send(images);
});
// parse the incoming request containing the form data
form.parse(req);
});
var server = App.listen(1000, function(){
console.log('Files Server listening on port 1000');
});