首页
学习
活动
专区
工具
TVP
发布
社区首页 >专栏 >浅谈h5文件上传

浅谈h5文件上传

作者头像
江米小枣
发布2020-06-16 17:11:09
2.4K0
发布2020-06-16 17:11:09
举报
文章被收录于专栏:云前端云前端云前端

前言

近期的需求中包含了上传头图(图片)和上传菜品(excel文件)的功能,商家可灵活上传使用自己制作的问卷图片,用户评价上传的菜品。

今天就针对我在做图片上传和excel上传时遇到的一些问题,跟大家分享一下

一、选择文件功能
  • 相信大家都知道,要在前端实现图片的上传,我们离不开的是一个 <input>type=file 的 input 元素,该元素可以允许用户选择一个或者多个文件。 该元素包含一个文本输入字段,用来输入文件名,还有一个按钮,用来打开文件选择对话框,以便图形化选择文件。
  • 属性
  • accept : 设置或返回文件传输的MIME类型的列表(英文逗号分隔) 1. accept='image/png' 或者 accept='.png' 表示只接受 .png 格式的图片 2. accept='iamge/png,image/jpeg' 格式的图片 3. accept='image/*' 接受所有类型的 image 注:image/*在部分浏览器(Chrome和Safari等Webkit浏览器)响应比较慢,可以按照第二种方式展示 imgage/png,image/ipeg
  • defaultValue : 设置或返回初始值
  • value : 保存了用户知道的文件的名称(只读属性)
  • alt : 设置或返回不支持<input type="file" />显示替代的文字
  • disable : 设置或返回是否禁用
  • multiple : 如果使用该属性,则字段可接受多个值.通过input:file的属性files可以看到现在是选择了3个文件,返回的是一个文件列表数组

就这样,一个简单的文件选择的功能咱们就做好了,可以设置属性来限制文件上传的格式、大小等来优化咱们的功能。 当然,这时你会发现:

  1. HTML自带的上传按钮比较丑,如何对其进行美化呢?
  2. 文件是选择了,但是选择的图片我怎么预览呢
  3. 怎么提交给后台呢,提交给后台什么呢

咱们一步步来完善

二、input[type=file] 样式美化
思路:

先把之前的按钮透明度opacity设置为0,然后外层用div包裹,就实现了美化功能

代码如下:

DOM结构:

<div className="file_upload">
   选择文件
   <input
       id="myFile"
       type="file"
       name="inputFile"
       onChange={this._onChangeInputFile.bind(this)} />
</div>

CSS样式:

.file_upload {
   position: relative;
   width: 100px;
   height: 40px;
   line-height: 40px;
   text-align: center;
   border-radius: 6px;
   background-color: #79d479;
   color: #fff;
}
.file_upload input {
   position: absolute;
   width: 100%;
   height: 100%;
   opacity: 0;
   top: 0;
   left: 0;}

修改前后如下:(也可以看一下manage_v2017项目中“图片预览”组件的样式美化)

三、文件上传
1、上传图片并预览
  • 选择图片,预览(base64),不真正传给后台,而是页面保存的时候传给后台(base64格式)
  • 选择图片,预览(base64),上传给后台,后台返回图片地址(url),保存页面时,再次提交上传成功后后台返回的图片地址(url)
  • 选择图片,上传给后台,后台返回图片地址(url),页面预览,保存页面时,再次提交上传成功后后台返回的图片地址(url)

如果我们先将图片上传到服务器,然后在将返回结果显示在前端,这样的操作性能开销太大,如果图片很多,就比较慢了。

  • FileList对象

选中文件通过 HTMLInputElement.files 属性返回了一个 FileList 对象,这个对象是一个包含了许多 file 文件的列表。每个 file 对象包含了一下信息:

  1. name:文件名
  2. lastModified:文件最后一次修改时间(时间戳形式)
  3. lastModifiedDate:文件最后一次修改时间(UNIX timestamp形式)
  4. size: 文件大小(byte 为单位)
  5. type:文件 MIME 类型

我们可以通过对input的change事件监听,获取FileList.

const files = document.getElementById('uploadFile').files;
let fileObj = files[0];
  • FileReader

当我们获取到文件信息files后,需要将选择的图片展示在页面上,要用到FileReader;他是用来把文件读入内存,并且读取文件中的数据。它提供了一个异步的API,使用该API可以在浏览器主线程中异步访问文件系统,读取文件中的数据。他必须先通过 FileReader() 构造函数创建出一个 fileReader 实例,实现图片预览要用到它的几个方法和属性。想要了解FileReader更多

<img src="" id="PreviewImg" />
<input type="file" id="uploadImg" onChange={this._onChangeImg.bind(this)} />_onChangeImg(e) {
   let fileObj = document.getElementById("uploadImg").files[0],
       PreviewImg = document.getElementById("PreviewImg"),
       reader = new FileReader();   // 读取文件并以数据 URI 形式保存在 result 属性中
   reader.readAsDataURL(fileObj);   // 在文件加载成功后触发 load 事件
   reader.onload = function(e) {
       let imgUrl = e.target.result;
       PreviewImg.src = imgUrl;
   }   // 在文件加载失败后触发 error 事件
   reader.onerror = function(e) {}}
  1. 调用FileReader对象的方法

FileReader 的实例拥有 4 个方法,其中 3 个用以读取文件,另一个用来中断读取。下面列出了这些方法以及他们的参数和功能,需要注意的是 ,无论读取成功或失败,方法并不会返回读取结果,这一结果存储在 result属性中。

  • abort [none] 中断读取
  • readAsBinaryString [file] 将文件读取为二进制码
  • readAsDataURL [file] 将文件读取为 DataURL
  • readAsText [file] 将文件读取为文本
  • readAsText:该方法有两个参数,其中第二个参数是文本的编码方式,默认值为 UTF-8。这个方法非常容易理解,将文件以文本方式读取,读取的结果即是这个文本文件中的内容。
  • readAsBinaryString:该方法将文件读取为二进制字符串,通常我们将它传送到后端,后端可以通过这段字符串存储文件。
  • readAsDataURL:这是例子程序中用到的方法,该方法将文件读取为一段以 data: 开头的字符串,这段字符串的实质就是 Data URL,Data URL是一种将小文件直接嵌入文档的方案。这里的小文件通常是指图像与 html 等格式的文件。
  1. 处理事件

FileReader 包含了一套完整的事件模型,用于捕获读取文件时的状态,下面归纳了这些事件。

  • onabort 中断时触发
  • onerror 出错时触发
  • onload 文件读取成功完成时触发
  • onloadend 读取完成触发,无论成功或失败
  • onloadstart 读取开始时触发
  • onprogress 读取中 文件一旦开始读取,无论成功或失败,实例的 result 属性都会被填充。如果读取失败,则 result 的值为 null ,否则即是读取的结果,绝大多数的程序都会在成功读取文件的时候,抓取这个值。
  • 对象URL

使用对象 URL 的时候不用像 FIleReader 一样要先把数据读取到 JavaScript 中,他可以引用 内存中 URL 地址而使用。

创建对象 URL 方法: window.URL.createObjectURL()。兼容写法:

<img src="" id="PreviewImg" />
<input type="file" id="uploadImg" onChange={this._onChangeImg.bind(this)} />
                       
                       
function creatObjectURL(file) {
   if (window.URL) {
       return window.URL.createObjectURL(file);
   } else if (window.webkitURL) {
       return window.webkitURL.createObjectURL(file);
   } else {
       return null
   }
}_onChangeImg(e) {
   let fileObj = document.getElementById("uploadImg").files[0],
       PreviewImg = document.getElementById("PreviewImg");   let url = this.createObjectURL(fileObj);
   PreviewImg.src = url;}

区别: 参(zhao)考(chao)

FileReader 是异步操作,而对象 URL 是同步操作FileReader.readAsDataURL 返回的是一个包含更多字节的 base64 格式,createObejctURL 返回的是一个带 hash 的 URL。由于两者返回形式不同,FileReader.readerAsDataURL 会占用更多内存,但是当你不再使用他的时候,他会自动释放内存,而 createObjectURL 则只有当你的页面关闭或者手动调用 revokeObejctURL 的时候才能释放内存。从兼容性来说: createObjectURL 和 FileReader.readerAsDataURL 都兼容 IE10+ 和现代所有主流浏览器createObjectURL 相对 FileReader.readerAsDataURL,效率较高。但是如果图片较多,则最好手动清除内存,可以把 URL 当做参数直接传给 window.URL.revokeObjectURL()。兼容写法:
function revokeObjectURL(url) {
    if (widnow.URL) {
        return window.URL.revokeObjectURL(url)
    } else {
        return window.webkitURL.revokeObjectURL(url)
    }
}
文件预览(在线预览Web Office)

参考资料:

  1. https://juejin.im/post/5a0545a75188254d2b6d979c
  2. http://www.cnblogs.com/rubylouvre/p/4597344.html
  3. https://juejin.im/entry/59b3d193f265da065e320194
  4. http://www.cnblogs.com/cloudgamer/archive/2009/12/22/ImagePreview.html
  5. http://www.cnblogs.com/zhaopei/p/upload.html
  6. https://developer.mozilla.org/zh-CN/docs/Web/API/URL/createObjectURL
  7. blob:https://juejin.im/entry/5937c98eac502e0068cf31ae
本文参与 腾讯云自媒体分享计划,分享自微信公众号。
原始发表:2018-04-24,如有侵权请联系 cloudcommunity@tencent.com 删除

本文分享自 云前端 微信公众号,前往查看

如有侵权,请联系 cloudcommunity@tencent.com 删除。

本文参与 腾讯云自媒体分享计划  ,欢迎热爱写作的你一起参与!

评论
登录后参与评论
0 条评论
热度
最新
推荐阅读
目录
  • 前言
    • 一、选择文件功能
      • 二、input[type=file] 样式美化
        • 思路:
          • 三、文件上传
            • 1、上传图片并预览
              • 文件预览(在线预览Web Office)
              领券
              问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档