web前端之——图片上传

时间:2024-04-16 13:22:26

本文主要讨论以下两部分:

   一、实现图片及时预览,将用户选中的图片及时显示在前台页面(利用FileReader实现);不用通过后台接口返回的图片地址赋值给src再展示到前台,减少前后台的频繁交互;

   二、通过后台接口,将图片上传到服务器中(FormData)。


 

首先介绍一下h5新增的FileReader对象():

FileReader:读取文件内容

   1. readAsText(): 读取文本文件(可以使用Txt打开的文件),返回文本字符串,默认编码是UTF-8
   2. readAsBinaryString(): 读取任意类型的文件。返回二进制字符串。这个方法不是用来读取文件展示给用户看,而是存储文件。例如:读取文件的内容,获取二进制数据,传递给后台,后台接收了数据之后,再将数据存储
   3. readAsDataURL(): 读取文件获取一段以data开头的字符串,这段字符串的本质就是DataURL.DataURL是一种将文件(这个文件一般就是指图像或者能够嵌入到文档的文件格式) 嵌入到文档的方案。DataURL是将资源转换为base64编码的字符串形式,并且将这些内容直接存储在url中>>优化网站的加载速度和执行效率。
   4. abort():中断读取
 
FileReader 提供一个完整的事件模型,用来捕获读取文件时的状态
 - onabort: 读取文件中断片时触发
 - onerror: 读取错误时触发
 - onload: 文件读取成功完成时触发
 - onloadend: 读取完成时触发,无论成功还是失败
 - onloadstart: 开始读取时触发
 - onprogress: 读取文件过程中持续触发

 具体可以参考 https://www.cnblogs.com/hhhyaaon/p/5929492.html ,介绍的很详细。

一、实现图片及时预览

首先是html代码:

1 <form action="" enctype="multipart/form-data" method="post" name="form1" id="form1">
2    文件:<input type="file" name="myFile" id="myFile" onchange="getFileContent();" multiple>
3      <!-- 进度条 -->
4       <div></div>
5     <input type="submit">
6   </form>
7 <!-- 图片展示区域 --> 8 <ul id="imgList"></ul>

 

css样式:

 1 <style>
 2     ul{
 3       list-style: none;
 4     }
 5     li{
 6       float: left;
 7       border: 1px solid #000;
 8       margin: 10px;
 9     }
10     li img{
11       display:block;
12     }
13     div{
14       width: 0%;
15       height: 20px;
16       background-color: lightcoral;
17     }
18   </style>

 

页面效果是这样子:

1、上传 单个图片 的js代码:

 1  function getFileContent(){
 2   // file[0]就是上传的图片本身
 3   // FileReader的readAsDataURL方法可以将图片转换为base64格式
 4   // 1.上传单个文件时: 
 5       var reader = new FileReader();
 6       var file = document.querySelector("#myFile").files;
 7       reader.readAsDataURL(file[0]);
 8       // 一定要在文件读取 成功完成时 再进行相应的操作:
 9       reader.onload = function(){
10           document.querySelector("img").src = reader.result;
11       }
12   }

 

其中file打印出是:里面包含用户上传的文件名称、大小、类型,如果想限制图片大小和类型,可以自行添加判定条件~

2、上传 多个图片 的js代码:

    每上传一张图片(一个文件)就需要创新创建一个 FileReader 实例,否则会出现一些问题(只成功上传了选中的最后一张图片);

 这里将上传单个图片封装为一个函数,在循环遍历用户选择的文件时,一一上传图片,每个图片都有上传时的进度条。

 1 function getFileContent(){
 2       // 上传多个文件时:
 3       var file = document.querySelector("#myFile").files;
 4       var totalSize = 0;
 5       // 限定文件总数不能超过的大小
 6       var maxSize = 10*1024*1024; 
 7       for(var i=0;i<file.length;i++){
 8         totalSize += file[i].size;
 9         if(file[i].size > maxSize){
10           alert("文件不能超过10M")
11           return false;
12         }else{
13           // 调用上传多个图片的方法,传入的参数为:用户选中的文件 和 每个图片的 index
14           uploadMultiImg(file,i);
15         }
16       }
17  }
18 
19 // 上传多个图片的方法:
20     function uploadMultiImg(file,index){
21         var li = document.createElement("li");
22         ul.appendChild(li);
23         var img = document.createElement("img");
24         li.appendChild(img);
25         /*1.1 由于IE9以下没有FileReader,因此先判断是否支持FileReader  并且  创建文件读取对象*/
26          if(window.FileReader) {
27             var reader = new FileReader();
28         } else {
29             alert("您的设备不支持图片预览功能,如需该功能请升级您的设备!");
30         }
31         // 1.2 是否是图片
32         var imageType = /^image\//;
33         if(!imageType.test(file[index].type)) {
34           alert("请选择图片!");
35           return;
36         }
37          /*2.读取文件,获取DataURL
38         * 2.1.说明没有任何的返回值:void:但是读取完文件之后,它会将读取的结果存储在文件读取对象的result中
39         * 2.2.需要传递一个参数 binary large object:文件(图片或者其它可以嵌入到文档的类型)
40         * 2.3:文件存储在file表单元素的files属性中,它是一个数组*/
41         reader.readAsDataURL(file[index]);
42         /*获取数据*/
43         reader.onload = function(){
44           /*展示:图片路径设置为读取的图片*/
45           img.src = reader.result;
46           img.style.width = \'300px\';
47           img.style.height = \'300px\';
48         }
49 
50         // 进度条
51         reader.onprogress = function(e){
52           var percent = e.loaded / e.total * 100 + \'%\';
53           div.style.width = percent;
54           var number = (e.loaded / e.total * 100).toString().substring(0,5) + \'%\';
55           div.innerText = number;
56         }
57     }

进度条是通过reader.onprogress()方法实现,打印e:loaded是已上传的大小,total是文件总大小。通过二者的比例可以自定义一个进度条。

最终效果:

二、将图片上传到服务器中(FormData对象)

参考文章:

https://blog.****.net/lijia_1983370657/article/details/80489979

https://blog.****.net/thunderevil35/article/details/80953236

https://www.cnblogs.com/hutuzhu/p/4409292.html

 

使用 h5的 formData 对象 用ajax异步的方式提交form表单(还可以实现异步提交文件)

 在使用 jquery 发送图片到后台时要注意几点:

  •  <form>标签添加 enctype="multipart/form-data" 属性
  •  jQuery 的 ajax 中 processData 设置为 false (表示不需要对数据做处理)
  •  jQuery 的 ajax 中 cache 设置为 false (表示上传文件不需要缓存)
  •  jQuery 的 ajax 中 contentType 设置为 false (因为前面已经声明了是‘FormData对象’)

 如果没有<form>标签,也没有 enctype="multipart/form-data" 属性,可以使用 FormData 的 append() 方法来手动添加 如用户名、文件等内容。

 1 var formData = new FormData($(\'#form1\'));
 2 // formData.append(\'images\', $(\'#myFile\')[0].files);
 3 //ajax请求
 4 $.ajax({
 5             type: "post",
 6             url:  "接口地址",
 7             data: formdata,
 8             dataType: \'json\',
 9             processData: false, // 告诉jQuery不要去处理发送的数据
10             contentType: false, // 告诉jQuery不要去设置Content-Type请求头
11             xhrFields:{withCredentials:true},
12             async: true,    //默认是true:异步,false:同步。
13             success: function (data) {
14                 callback(data);
15             },
16             error: function (data) {
17                 layer.msg(\'请求异常\');
18             },
19 });

如果使用原生js实现,如下代码:

 1 function fsubmit() {
 2        var form=document.getElementById("form1");
 3        var formData=new FormData(form);
 4        var oReq = new XMLHttpRequest();
 5        oReq.onreadystatechange=function(){
 6            if(oReq.readyState==4){
 7               if(oReq.status==200){
 8                   var json=JSON.parse(oReq.responseText);
 9                   var result = \'\';
10                   // result += \'name=\' + ret[\'name\'] + \'<br>\';
11                   // result += \'gender=\' + ret[\'gender\'] + \'<br>\';
12                   result += \'<img src="\' + json[\'photo\'] + \'" width="100">\';
13                   $(\'#result\').html(result);
14               }
15             }
16         }
17         oReq.open("POST", "server.php");
18         oReq.send(formData); 
19         return false;
20 }