起源
我之前一直做的是单图上传,或者单图上传加预览的模式,实现起来都不是那么麻烦,下面都会提到。
而今天给自己挖了个坑,批量上传多张图片,类似这样:
选择上传文件.png然后我还特想装13,想研究下原理。
从头说这件事
文件上传,html的基础表单组件就提供了该功能的实现,使用非常简单的表单提交就能做。然而可能一些pm觉得图片能实时预览是非常好的用户体验,这时候可以用js来构建form表单异步上传。再往后推,就要求既能批量上传,又能实时预览。说白了感觉用户体验什么的借口感觉都是在挖坑给我们写代码的。
cp1 表单上传
代码优先发言:
<form action="index.php" method="post" enctype="multipart/form-data">
<input type="file" name="file">
<input type="submit" value="提交">
</form>
效果图发言:
表单文件上传效果.png这个体验确实不好,只有文件名,没有文件的内容预览。
后端代码贴个servlet3的
先把servlet加上 <code>@MultipartConfig(maxFileSize=1024x1024x10)</code> 注解,然后逻辑代码如下:
Part part=request.getPart("file");
if (null!=part&&part.getSize()>0) {
InputStream inputStream=part.getInputStream();
ByteArrayOutputStream outputStream=new ByteArrayOutputStream();
byte[] buffer = new byte[1024*100];
int len=0;
while ((len=inputStream.read(buffer,0,buffer.length))>0) {
outputStream.write(buffer,0,len);
}
byte[] fileByte=outputStream.toByteArray();
}
拿到byte数组后面的操作代码我就不贴了,有的存本地文件,有的上传到文件服务器,这个因项目架构而定,反正servlet3的后端逻辑差不多就是这样,至于使用其他框架的自行查询对照实现。
cp2 异步上传预览
效果图优先发言:
上传表情并预览.png这里我使用 jquery 的 fileupload 实现的,当然也有很多极简爱好者自己实现,原理也很简单。
前端代码,跟上面结构一致
<form action="index.php" method="post" enctype="multipart/form-data">
<input id="selectFile" type="file" name="file">
<input type="submit" value="提交">
</form>
js代码
$("#selectFile").fileupload({
dataType: "json",
url: "/upload/singleFile",
type: "POST",
done: function(e, data) {
$("#selectFile").before('<img src="'+data.result.result+'"/>');
}
});
这里文件选择好后直接上传到后台,上传完成后插入一个img标签做预览效果。文件的上传和表单的提交是分开的!表单提交的时候只提交文件的编号或者地址,不包含任何文件。
使用框架的好处就是简单方便,缺点是不了解原理,高级特性没办法用。
异步上传文件的原理是,构造一个iframe进行上传,上传完成后获取iframe的内容,作为服务器的返回结果,前端拿到返回的结果后,构造img展示预览图。(这里本来要配代码,无奈之前收藏的书签丢失了,不过不重要,后面有更简单的方式)
cp3 批量上传并预览
虽然前面提到的 jquery 的 fileupload 插件能实现,但是作为一名极简主义者,自然是要自!己!开!发!
前端代码,input加入multiple属性
<form action="index.php" method="post" enctype="multipart/form-data">
<input id="selectFile" type="file" name="file" multiple="multiple">
<input type="submit" value="提交">
</form>
js代码:
因为坑挖的奇葩,需要在图片上传之前做一些前置操作,拿到选择图片的信息:
var files=$("#selectFile")[0].files;
for (var i = 0; i < files.length; i++) {
var file=files[i];
console.log(file);
}
看下打印出来的信息
lastModified:1471099234297
lastModifiedDate:Sat Aug 13 2016 22:40:34 GMT+0800 (中国标准时间)
name:"6.png"
size:26476
type:"image/png"
webkitRelativePath:""
不错,图片类型,大小,图片名都显示出来了,要做前置操作的在这里做抓紧做。
那么我们拿到文件的dom了怎么上传?当是我是懵逼的,因为文件上传,包括插件,单位都是 input ,这是input 里面的东西,怎么上传?
后来找到了一种方法,XMLHttpRequest,构造请求提交表单。构!造!请!求!这不是类似java的HttpClient吗?万能的工具!
核心代码:
var xhr = new XMLHttpRequest();
xhr.open('POST', "index.php", true);
var formData = new FormData();
formData.append('file', file); // file 为上面拿到的file对象
xhr.onreadystatechange = function(response) { // 文件上传完毕通知函数
console.log(xhr.responseText);
}
xhr.send(formData);
具体的实现参照前面cp2就能实现,这里篇幅有限,不多阐述。
结语
有时候js的原理确实该看看,反正又不难,半天的时间就能搞定。
愿每位码农都能在天梯上披襟斩棘,一统逼界,千秋万载。
网友评论