文档章节

Html5 ajax上传多个图片 +压缩 + nodjs保存

s
 snecker
发布于 2015/04/03 02:02
字数 1020
阅读 392
收藏 15
点赞 0
评论 0

nodejs端

可以安装multer插件,npm install multer

var express = require("express");
var multer = require('multer');
var _ = require('underscore')
var app = express();
var done = false;

/*配置允许ajax跨域*/
app.use(function (req, res, next) {
    res.header('Access-Control-Allow-Origin', '*');
    res.header('Access-Control-Allow-Methods', 'GET,PUT,POST,DELETE');
    res.header('Access-Control-Allow-Headers', 'Origin, X-Requested-With, Content-Type, Accept');
    next();
});

app.use(multer({
    dest: '../public/images/uploads/',
    rename: function (fieldname, filename) {
        return filename + Date.now();
    },
    onFileUploadStart: function (file) {
        console.log(file.originalname + ' is starting ...')
    },
    onFileUploadComplete: function (file) {
        console.log(file.fieldname + ' uploaded to  ' + file.path)
        done = true;
    }
}));

/*Handling routes.*/

app.get('/', function (req, res) {
    //输出上传页面
    res.sendfile("upload.html");
});

app.post('/api/upload', function (req, res) {
    if (done == true) {
        console.log(req.files);
        res.end(_.size(req.files)+" File uploaded.");
    }
});

/*Run the server.*/
app.listen(3000, function () {
    console.log("Working on port 3000");
});

前端

upload.html

<input id='upload' name="pic1" type="file" onchange="change(this)" multiple/>
<button id='add'>add</button>
<button id='submit' onclick="sub()">提交啊</button>

ajax

利用xhr.send(FormData)来实现


    var send2 = function(url, files) {
    		var xhr = new XMLHttpRequest;
    		xhr.open("POST", url, true);
    
    		xhr.onreadystatechange = function() {
    			if (xhr.readyState === 4) {
    				console.log('formdata', xhr.responseText);
    			}
    		};
    		var fd = new FormData;
    
    		for (var i = 0; i < files.length; i++) {
                        //如果多张图片文件名一样,需要设置不同name
                        var name = files[i].name + i;
    			fd.append(name , files[i])
    		}
    		xhr.send(fd);
    	};

利用拼接原始包的方式实现


		def('upload', function () {

	    'use strict';

	    var exports = {};

	    var prefix = '------';

	    var _boundary = "WebKitFormBoundaryLfG8DWAstG9WjKAt";//默认boundary

	    var boundaryWithPrefix = prefix + _boundary;   		

		exports.genBinString = function (data, files) {
        var CRLF = '\r\n';

        var genData = function (name, value) {
            value = value || '';
            return boundaryWithPrefix + CRLF +
                "Content-Disposition: form-data; name=\"" + name + "\"" + CRLF + CRLF                + value;
        }
        var genFile = function (name, fileName, type, bin) {
            return boundaryWithPrefix + CRLF                + 'Content-Disposition: form-data; name="' + name +'"; filename="' + fileName + '"' + CRLF                + 'Content-Type: ' + type + CRLF             + CRLF                + bin;
        };

        var resultBin = '';
        //resultBin += CRLF;
        for (var key in data) {
            resultBin += genData(key, data[key]) + CRLF;
        }
        //file
        for (var i = 0; i < files.length; i++) {
            var file = files[i];
            var type = exports.getMimeType(file.src);
            var bin = exports.getByteString(exports.compress(file.src));
            resultBin += genFile('images', file.name, type, bin) + CRLF;
        }
		resultBin += boundaryWithPrefix + '--' + CRLF;
	
		return resultBin;
		}

    	//兼容 end
   	 	exports.send = function (option) {
        var url = option.url, data = option.data, files = option.files, srcs = option.srcs,
            sucFn = option.sucFn, failFn = option.failFn,
            uploadStart = option.uploadStart, uploadProgress = option.uploadProgress, uploadSuccess = option.uploadSuccess, uploadError = option.uploadError;

        var xhr = new XMLHttpRequest;
        var upload = xhr.upload;
        //xhr.onprogress = updateProgress;//下载进度
        //上传进度
        upload.addEventListener("loadstart", uploadStart, false);
        upload.addEventListener("progress", uploadProgress, false);
        upload.addEventListener("load", uploadSuccess, false);
        upload.addEventListener("error", uploadError, false);

        xhr.open("POST", url, true);
        xhr.onreadystatechange = function () {
            if (xhr.readyState === 4 && xhr.status == 200) {
                sucFn(JSON.parse(xhr.responseText));
            }
        };
        xhr.onerror = failFn;
        xhr.withCredentials = true;

        var fd = new FormData;
        //data
        Object.keys(data).forEach(function (key) {
            fd.append(key, data[key])
        })
        //files
        var compressedDataURIs = [];
        //递归压缩图片
        function compressFiles(files, idx, onComplete) {
            if (!files) {
                return;
            }
            var dataUri = files[idx].src;
            if (dataUri) {
                var next = function (curCompressURI) {
                    //压缩包含base64头,去掉
                    //log('压缩后:' + curCompressURI)
                    curCompressURI = curCompressURI.split(',')[1];
                    compressedDataURIs[idx] = curCompressURI;

                    if (idx == files.length - 1) {
                        return onComplete(compressedDataURIs);
                    }
                    compressFiles(files, idx + 1, onComplete);
                }
                exports.compress(dataUri, 80, next);
            }
        }

        function uncompressFiles(files) {
            if (files && files.length) {
                files.forEach(function (file) {
                    fd.append('images', file);
                })
            }
        };
        //很多浏览器压缩没有效果,暂时去掉。
        uncompressFiles(files);
        xhr.send(fd);

        //递归方式start
	       /* if (files && files.length) {
	            compressFiles(srcs, 0, function (compressedArr) {
	                //所有图片已压缩
	                if (compressedArr.length == 0 || compressedArr.join('') == '') {
	                    uncompressFiles(files);
	                } else {
	                    fd.append('base64files', JSON.stringify(compressedArr));
	                }
	                xhr.send(fd);
	            })
	        } else {
	            xhr.send(fd);
	        }*/
        //递归方式end
        /* srcs.forEach(function (file, idx) {
         var dataUri = file.src;
         //gif图,不压缩
         var type = exports.getMimeType(dataUri);
         if (type.indexOf('gif') > -1) {
         var compressDataURI = dataUri;
         } else {
         //var compressDataURI = exports.compress(dataUri, 80);
         //已经压缩过;
         var compressDataURI = dataUri;
         }
         compressDataURI = compressDataURI.split(',')[1];
         compressedDataURIs.push(compressDataURI);
         //var imageFile = new File([imageBlob], 'images');
         });

         //压缩失败则原图上传
         if (compressedDataURIs.join('').length == 0) {
         files.forEach(function (file) {
         fd.append('images', file);
         })
         } else {
         fd.append('base64files', JSON.stringify(compressedDataURIs));
         }*/
        //xhr.send(fd);
        //xhr.send(exports.genBinString(data, files));
    	}

    	//source:dataURI or img; img url保证base64;
    	exports.compress = function (source, quality, onCompressed) {
        var sourceImg = new Image();
        sourceImg.onload = function () {
            var cvs = document.createElement('canvas')

            var w = sourceImg.naturalWidth;
            var h = sourceImg.naturalHeight;
            var ratio = Math.max(w, h) / 1024;
            ratio = Math.max(1, ratio);
            cvs.width = w / ratio;
            cvs.height = h / ratio;
            var ctx = cvs.getContext("2d").drawImage(sourceImg, 0, 0, cvs.width, cvs.height);

            var mime_type = sourceImg.src.split(',')[0].split(':')[1].split(';')[0];
            var compressedDataURI = cvs.toDataURL(mime_type, quality / 100);
            //log('压缩前:' + source.length + '压缩后:' + compressedDataURI.length);
            onCompressed && onCompressed(compressedDataURI);
        }
        sourceImg.src = source;
        //return compressedDataURI;
   		}

    	//dataURI to Blob;
    	exports.dataURItoBlob = function (dataURI) {
        var byteString = exports.getByteString(dataURI);

        // separate out the mime component
        var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
        // write the bytes of the string to a typed array
        var ia = new Uint8Array(byteString.length);
        for (var i = 0; i < byteString.length; i++) {
            ia[i] = byteString.charCodeAt(i);
        }
        var blob = null;
        try {
            blob = new Blob([ia], {type: mimeString});
        } catch (e) {
            //see http://stackoverflow.com/questions/15293694/blob-constructor-browser-compatibility
            window.BlobBuilder = window.BlobBuilder ||
            window.WebKitBlobBuilder ||
            window.MozBlobBuilder ||
            window.MSBlobBuilder;

            if (e.name == 'TypeError' && window.BlobBuilder) {
                alert('blobbuilder')
                var bb = new BlobBuilder();
                bb.append([ia.buffer]);
                blob = bb.getBlob(mimeString);
            }
            else if (e.name == "InvalidStateError") {
                // InvalidStateError (tested on FF13 WinXP)
                blob = new Blob([ia.buffer], {type: mimeString});
            }
            else {
                // We're screwed, blob constructor unsupported entirely
                alert('此浏览器暂不支持上传!')
            }
        }
        return blob;
    	};

	    //convert base64/URLEncoded data component to raw binary data held in a string
	
	    exports.getByteString = function (dataURI) {
	        var byteString = '';
	        if (dataURI.split(',')[0].indexOf('base64') >= 0)
	            byteString = atob(dataURI.split(',')[1]);
	        else
	            byteString = unescape(dataURI.split(',')[1]);
	        return byteString;
	    }
	
	    exports.getMimeType = function (dataURI) {
	        return dataURI.split(',')[0].split(':')[1].split(';')[0];
	    }
	
	    return exports;
	
		})

##注:

1.问:图片压缩在iphone和一些android手机上并没有多大效果,不知道问题在哪,pc上模拟mobile确是好的

2.问:图片上传的upload。progress事件在ios6上好像没有作用。

3 扩展:压缩时可以等比缩小图片以减少上传流量,如width或height大于1024px,则按照1024的比例缩小

© 著作权归作者所有

共有 人打赏支持
s
粉丝 1
博文 41
码字总数 9798
作品 0
长沙
技术主管
php canvas 前端JS压缩,获取图片二进制流数据并上传

效果图(canvas压缩图片会失真): 参考: php canvas 前端JS压缩,获取图片二进制流数据并上传 https://www.cnblogs.com/-mrl/p/8708114.html js+php如何实现上传图片 https://www.jianshu....

豆花饭烧土豆
05/30
0
0
HTML5 FormData+Ajax上传文件表单

文件表单的数据类事multipart/form-data,因此,formData需要特殊处理. 文件上传 参考文章: HTML5 + AJAX ( 原生JavaScript ) 异步多文件上传 [HTML5] Blob对象 通过Ajax方式上传文件,使用...

IamOkay
2017/10/31
0
0
使用jQuery开发一个基于HTML5的漂亮图片拖拽上传web应用

日期:2011/11/19 来源:GBin1.com 昨天我们介绍了一款HTML5文件上传的jQuery插件:jQuery HTML5 uploader ,今天我们将开发一个简单的叫upload center的图片上传程序,允许用户使用拖拽方式...

gbin1
2011/11/19
0
1
(转载学习)文件上传的渐进式增强

本文为转载学习 原文作者:阮一峰 原文链接:http://www.ruanyifeng.com/blog/2012/08/fileupload.html HTML5提供了一系列新的浏览器API,使得文件上传有可能出现革命性变化。英国程序员Rem...

heroShane
2014/01/24
0
0
使用HTML5构建下一代的Web Form

作者 蒋博 发布于 2009年6月22日 上午4时52分 HTML5 是由 WHATWG (Web Hypertext Application Technology Working Group) 发起的,最开始的名称叫做Web Application 1.0,而后这个标准吸纳了...

晨曦之光
2012/03/09
0
0
利用HTML5分片上传超大文件

在网页中直接上传大文件一直是个比较头疼的问题,主要面临的问题一般包括两类:一是上传时间长中途一旦出错会导致前功尽弃;二是服务端配置复杂,要考虑接收超大表单和超时问题,如果是托管主...

miscellanea
2014/09/22
0
0
7款基于JavaScript和AJAX的文件上传插件

本文整理了7款基于JavaScript和AJAX的文件上传插件,这些插件基本上都能实现以下功能: 多文件上传 拖拽操作 实时上传进度 自定义上传限制 希望能为你的开发工作带来帮助。 1. jQuery File U...

EDIAGD
2013/09/23
0
0
JS原生系列-DOM篇(延伸)

关于DOM,这就是最后一部分了,这部分都是后台或者最新的dom api,学的时候需要多的记忆一次,有印象有保障! -.ajax的介绍:ajax输出json格式文件 jsonp的介绍 xhr2的介绍 http://www.w3sch...

透笔度
2015/08/10
0
1
何崚谈阿里巴巴前端性能优化最佳实践

大家好,我现在在阿里巴巴园区采访阿里巴巴中文站架构师,兼B2B网站优化领域的负责人何崚。何崚你好,请简单介绍一下你自己。 我叫何崚,2006年加入阿里巴巴。之前一直在中科院下属的两个基因...

zjf_sdnu
2011/10/14
0
0
HTML5时代来了,还不为你的Visual Studio 2010添加HTML5的项目模板!!!

HTML5时代来了,还不为你的Visual Studio 2010添加HTML5的项目模板!!! 本文在简单不过了,就是为你的Visual Studio2010创建一个项目模板,一个HTML5的项目模板。谁叫HTML5时代来了,Visua...

晨曦之光
2012/03/09
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

Android 复制和粘贴功能

做了一回搬运工,原文地址:https://blog.csdn.net/kennethyo/article/details/76602765 Android 复制和粘贴功能,需要调用系统服务ClipboardManager来实现。 ClipboardManager mClipboardM...

她叫我小渝
23分钟前
0
0
拦截SQLSERVER的SSL加密通道替换传输过程中的用户名密码实现运维审计(一)

工作准备 •一台SQLSERVER 2005/SQLSERVER 2008服务 •SQLSERVER jdbc驱动程序 •Java开发环境eclipse + jdk1.8 •java反编译工具JD-Core 反编译JDBC分析SQLSERVER客户端与服务器通信原理 SQ...

紅顏為君笑
39分钟前
4
0
jQuery零基础入门——(六)修改DOM结构

《jQuery零基础入门》系列博文是在廖雪峰老师的博文基础上,可能补充了个人的理解和日常遇到的点,用我的理解表述出来,主干出处来自廖雪峰老师的技术分享。 在《零基础入门JavaScript》的时...

JandenMa
56分钟前
0
0
linux mint 1.9 qq 安装

转: https://www.jianshu.com/p/cdc3d03c144d 1. 下载 qq 轻聊版,可在百度搜索后下载 QQ7.9Light.exe 2. 去wine的官网(https://wiki.winehq.org/Ubuntu) 安装 wine . 提醒网页可以切换成中...

Canaan_
今天
0
0
PHP后台运行命令并管理运行程序

php后台运行命令并管理后台运行程序 class ProcessModel{ private $pid; private $command; private $resultToFile = ''; public function __construct($cl=false){......

colin_86
今天
1
0
数据结构与算法4

在此程序中,HighArray类中的find()方法用数据项的值作为参数传递,它的返回值决定是否找到此数据项。 insert()方法向数组下一个空位置放置一个新的数据项。一个名为nElems的字段跟踪记录着...

沉迷于编程的小菜菜
今天
1
1
fiddler安装和基本使用以及代理设置

项目需求 由于开发过程中客户端和服务器数据交互非常频繁,有时候服务端需要知道客户端调用接口传了哪些参数过来,这个时候就需要一个工具可以监听这些接口请求参数,已经接口的响应的数据,这种...

银装素裹
今天
0
0
Python分析《我不是药神》豆瓣评论

读取 Mongo 中的短评数据,进行中文分词 对分词结果取 Top50 生成词云 生成词云效果 看来网上关于 我不是药神 vs 达拉斯 的争论很热啊。关于词频统计就这些,代码中也会完成一些其它的分析任...

猫咪编程
今天
0
0
虚拟机怎么安装vmware tools

https://blog.csdn.net/tjcwt2011/article/details/72638977

AndyZhouX
昨天
1
0
There is no session with id[xxx]

参考网页 https://blog.csdn.net/caimengyuan/article/details/52526765 报错 2018-07-19 23:04:35,330 [http-nio-1008-exec-8] DEBUG [org.apache.shiro.web.servlet.SimpleCookie] - Found......

karma123
昨天
0
0

没有更多内容

加载失败,请刷新页面

加载更多

下一页

返回顶部
顶部