您的位置:首页 > Web前端 > CSS

做多文件/图片上传应该注意的几个前后端问题

2018-03-13 09:54 691 查看
最近在做微信端的文件上传,遇到了几个问题,折腾完后这里统一总结下,希望对其他人能有点帮助。

我前端未使用其他上传组件,用的原生的HTML、JS、CSS。

废话不多说,直接罗列你可能关心的点:

前端:

1.html自带file控件样式丑陋,如何达到UI设计要求效果;

2.选择图片后,按照一定的样式回显示图片如何实现;

3.无刷新提交;

4.form序列化无法提交二进制文件(这里是针对Query ajax的serialize()而言),该如何提交文件类型;

5.JS选择器获取单个文件、“multiple”类型多文件及非“multiple”类型的多个同类型input控件文件;

后端:

6.如何在后端接收文件类型(这里特指spring框架)

7.文件传入为空后端报错如何解决;

8.如何在后端接收一组文件;

9.写入文件;

实现(以下实现中,只截取了必要的代码)

问题1: html自带file控件样式丑陋,如何达到UI设计要求效果;

html默认的file控件样式往往达不到我们的要求,所以需要采用一定的css样式达到UI设计的效果。

我们先看下没有添加任何样式的file类型input控件的样式:



我们期望的样式,for example:



实现的HTML、CSS:

<!DOCTYPE html>
<html>
<head>
<title></title>
<style type="text/css">
html,body{
margin:0;
padding:0;
}
img{
width: 100px;
height: 100px;
border:1px dotted blue;
}
input{
width:100px;
height:100px;
z-index: 999;
opacity: 0;
position: absolute;
left: 0;
top: 0;
}
</style>
</head>
<body>
<img id="preview" src="http://avatar.csdn.net/E/A/1/3_irokay.jpg" alt="">
<input id="file" type="file" name="file">
</body>
</html>


效果图:



请自行把我的头像脑补成UI设计中的图片 - -!重点在于opacity、z-index、positon,然后调整位置使之大小、位置重合即可。

问题2: 选择图片后,按照一定的样式回显示图片如何实现;

我们采用FileReader对象的readAsDataURL回显图片,下面是介绍:

FileReader对象的readAsDataURL方法可以将读取到的文件编码成Data URL。Data URL是一项特殊的技术,可以将资料(例如图片)内嵌在网页之中,不用放到外部文件。使用Data URL的好处是,您不需要额外再发出一个HTTP 请求到服务器端取得额外的资料;而缺点便是,网页的大小可能会变大。它适合应用在内嵌小图片,不建议将大图像文件编码成Data URL来使用。您的图像文件不能够超过浏览器限定的大小,否则无法读取图像文件。

JS代码:

<script type="text/javascript">
function previewImg(){
let preview = document.querySelector('img[id=preview]');
let file = document.querySelector('input[id=file]').files[0];
let reader = new FileReader();
reader.onloadend = function () {
preview.src = reader.result;
}
if (file) {
reader.readAsDataURL(file);
} else {
preview.src = "";
}

}
</script>


问题3: 无刷新提交

这里采用原始的ajax提交,jquery ajax提交见我的另外一篇博客:

http://blog.csdn.net/irokay/article/details/72984048

步骤:

1)let request = new XMLHttpRequest()

2)request.open(“POST”, url)

3)request.onload = function(oEvent) {

if (request.status == 200) {

//alert(“success”);

} else {

//alert(“出错啦!请稍后再试。” + request.status);

}

};

4) request.send(formData);

问题4: form序列化无法提交二进制文件(这里是针对Query ajax的serialize()而言),该如何提交文件类型;

若采用Jquery ajax,序列化(serialize())表单是无法序列化二进制数据的,故我们采用FormData的方式提交文件类型。FormData对浏览器版本的要求见上面博客地址。当然我们这里没有采用jquery封装的ajax提交。

注:我这里是移动开发,移动端浏览器内核版本还是比较高的,所以使用FormData无问题。

FormData的使用:

let formData = new FormData();

//FormData添加文件类型:
formData.append("file",document.querySelector('input[id=file]').files[0]);


问题5: JS选择器获取单个文件、“multiple”类型多文件及非“multiple”类型的多个同类型input控件文件;

这里重点说一下。

1)单个文件的选择上述已经写到:

document.querySelector('input[id=file]').files[0]


2)若是“multiple”类型的input控件,即一个input控件可以同时选择多个文件(<input type=”file” multiple=”multiple” />);

选择器获取的写法:

<input id="file" type="file" multiple="multiple" />
//获取一个多选input file控件上的文件
document.querySelector('input[id=file]').files;
//alert("length:" + document.querySelector('input[id=file]').files.length);


3) 我们考虑下另外一种方式,采用追加的方式实现多图预览,譬如有多个id同为file的input组件,且全是单选(非multiple),这些照片为一组,需要统一获取并上传。

选择器获取方法为:

let files = document.querySelectorAll('input[id=file]');
let formData = new FormData();
for(let i = 0; i < files.length; i++){
//alert("路径为:" + files[i].value);
//alert("file对象:" + files[i].files[0]);
//将一组文件类型追加至file集合中
formData.append("file",files[i].files[0]);
}


这样即可将一组文件加入FormData的同一key下,一同提交。

问题6: 如何在后端接收文件类型(这里特指spring框架)

//接收单个文件
//且file文件不可为空,否则报错
public void savePic(@RequestParam("file") CommonsMultipartFile file,HttpServletRequest request, HttpServletResponse response,) throws IOException {...}


问题7:文件传入为空后端报错如何解决;

若前端未传入任何文件,上述写法会报错:

Cannot convert value of type [java.lang.String] to required type [org.springframework.web.multipart.commons.CommonsMultipartFile]

当前端传入文件可能为空时,后端接收不可写入方法参数中,避免报错。正确写法如下:

MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
MultipartFile file = multipartRequest.getFile("file"); //获取单个文件
//为空判断以及处理等...


问题8: 如何在后端接收一组文件;

MultipartHttpServletRequest multipartRequest = (MultipartHttpServletRequest) request;
//MultipartFile file = multipartRequest.getFile("file"); 获取单个文件
List<MultipartFile> fileList = multipartRequest.getFiles("file"); //获取一组文件
if(null != fileList && fileList.size()>0){
for(int i = 0; i < fileList.size(); i++){
System.out.println("第(" + i + ")个文件名:" + fileList.get(i).getOriginalFilename());
}
}


问题9: 写入文件;

File newFile=new File(path);
//通过CommonsMultipartFile的方法直接写文件
file.transferTo(newFile);
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息