专栏首页佛曰不可说丶面试题:我现在上传图片的时候提前预览到图片怎么办?

面试题:我现在上传图片的时候提前预览到图片怎么办?

今天我也来标题党一会,用“面试题”蹭一蹭热度,主要还行想深度剖析一下,文件上传,里面的门道。

1、在web上怎么实现文件上传

在我们使用的各种类库,框架中文件上传长相多样,百花齐放,但是归根结底还是离不开一个input标签,据我所知,所有的文件上传都是 html(如有别的方式请大佬指正) input标签 来实现上传,写法如下:

<input type="file" id="file" />

长相如下:

我们发现最原始的的上传,其实就就张这样,朴实无华,后来的那些框架和库,其实就是隐藏了这个朴实无华的input 而加入了很多华丽的样式,来操纵这个input

比如你看饿了么的这个上传改的相当的花里胡哨,那我们上传之后会得到什么呢?如下图:

其实这个input的dom对象下面会有个fileList对象,上传之后会存储当前这个文件的所有信息,实际上,这个fileLlist,就是一个blob对象,

什么是blob对象

Blob,Binary Large Object的缩写,代表二进制类型的大对象。Blob的概念在一些数据库中有使用到,例如,MYSQL中的BLOB类型就表示二进制数据的容器。在Web中,Blob类型的对象表示不可变的类似文件对象的原始数据,通俗点说,就是Blob对象是二进制数据的容器,用直观的方式去描述这个二进制数据 实际上这个fileList就是一个特殊的blob对象

blob如何使用呢?

构建一个Blob对象通常有三种方式:

1、通过Blob对象的构造函数来构建。

2、从已有的Blob对象调用slice接口切出一个新的Blob对象。

3、canvas API toBlob方法,把当前绘制信息转为一个Blob对象。

下面只看第一种的实现

//构造函数来构建
var blob = new Blob(array[optional], options[optional]);

构造函数,接受两个参数

第一个参数:为一个数据序列,可以是任意格式的值,例如,任意数量的字符串,Blobs 以及 ArrayBuffers。 第二个参数:用于指定将要放入Blob中的数据的类型(MIME)(后端可以通过枚举MimeType,获取对应类型

Blob对象的基本属性:

size :Blob对象包含的字节数。(只读)

type : Blob对象包含的数据类型MIME,如果类型未知则返回空字符串。

Blob对象的基本方法:

大文件分割 (slice() 方法),slice方法与数组的slice类似。

此时一个blob对象就创建好了,在上一部分中,我说fileList是个特殊的blob,你可以发现他其实是在blob的两大属性上加了几个别的属性,来具体的描述整个文件

blob有啥作用呢?

1、大文件上传

得益于blob的slice方法

当要上传大文件的时候,此方法非常有用,可以将大文件分割分段,然后各自上传,因为分割之后的 Blob 对象和原始的是独立存在的。

不过目前浏览器实现此方法还没有统一,火狐使用的是 mozSlice() ,Chrome 使用的是 webkitSlice() ,其他浏览器则正常的方式 slice()

//这里提供一个兼容写法
   function sliceBlob(blob, start, end, type) {
      type = type || blob.type;
      if (blob.mozSlice) {
          return blob.mozSlice(start, end, type);
      } else if (blob.webkitSlice) {
          return blob.webkitSlice(start, end type);
      } else {
          throw new Error("This doesn't work!");
      }

生成Blob链接,用于隐藏真实链接

某个时间开始我们打开调试工具去看各大视频网站的视频src会发现,它们统统变成了这样的形式。

这其实是为了防止盗链,而让后台传入的一段二进制流,我们在给包装成blob对象,存在内存中后,在给转成可以播放的链接,这样就有效防止了真是链接的泄露,接下来我们一步步深度剖析(可能有不对之处,请大佬随之批评指正)! 1、首先第一步,我们得有一个视频网址,然后,我们通过ajax获取 2、第二部后台得给这个链接转化成一个二进制的流,我们用blob对象,给他装进去, 3、用URL.createObjectURL方法,生成一个blob url 4、给这个blob url赋值到video的src上,浏览器就会自动解析地址,播放视频

废话少说,下上代码

       //创建XMLHttpRequest对象
        var xhr = new XMLHttpRequest();
        //配置请求方式、请求地址以及是否同步
        xhr.open('POST', '二进制流的地址', true);
        //设置请求结果类型为blob
        xhr.responseType = 'blob';
        //请求成功回调函数
        xhr.onload = function(e) {
            if (this.status == 200) {//请求成功
                //获取blob对象
                var blob = this.response;
                //获取blob对象地址,并把值赋给容器
                document.getElementById("video").src = URL.createObjectURL(blob);
            }
        };

上述代码有一个知识点:

URL.createObjectURL

URL.createObjectURL() 静态方法会创建一个 DOMString,其中包含一个表示参数中给出的对象的URL。这个 URL 的生命周期和创建它的窗口中的 document 绑定。这个新的URL 对象表示指定的 File 对象或 Blob 对象。

也就是说使用这个方法去创建一个DOMstring 引用这这个内存中的二进制流,然后在赋值到video标签上去就能达到隐藏链接的目的

  var debug = { hello: "world" };
  var blob = new Blob([JSON.stringify(debug, null, 2)], { type: 'application/json' });
   console.log(blob)
   var url = URL.createObjectURL(blob)
   console.log(url)

如此真实的链接就会被隐藏,并且这个链接是会动态变化,他在被video解析之后指向的地址就是个二进制文件的空间地址,看不见摸不着

解析到此,回归正题

2、现在上传图片的时候提前预览到图片怎么办?

废话少说先上代码:

//html
 <input type=file>
//js
//拿到当前的input
  const input = document.querySelector('input[type=file]')
     //监听改变,如此能拿到文件上传的特殊的blob对象,上文介绍过
        input.addEventListener('change', () => {
            //函数被执行,说明已经上传了文件
            console.log(input.files)
             //new一个fileReader对象,至于为啥先卖个关子
            const reader = new FileReader()
            reader.readAsDataURL(input.files[0]) // input.files[0]为第一个文件
            //成功之后赋值
            reader.onload = () => {
                const img = new Image()
                img.src = reader.result
                document.body.appendChild(img)  // reader.result为获取结果
            }
        }, false)

效果如下,我们发现我图片还没调用接口上传到服务器呢,就已经能预览了

下面我们来说一下卖的这个关子

FileReader是啥?

FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 File 或 Blob 对象指定要读取的文件或数据。

下面我们开看看他的一台方法:

FileReader.readAsArrayBuffer()

开始读取指定的 Blob中的内容, 一旦完成, result 属性中保存的将是被读取文件的 ArrayBuffer 数据对象.

**FileReader.readAsBinaryString() **

开始读取指定的Blob中的内容。一旦完成,result属性中将包含所读取文件的原始二进制数据。

FileReader.readAsText()

开始读取指定的Blob中的内容。一旦完成,result属性中将包含一个字符串以表示所读取的文件内容。

FileReader.readAsDataURL()

开始读取指定的Blob中的内容。一旦完成,result属性中将包含一个data: URL格式的Base64字符串以表示所读取文件的内容。这个是我们要用到的,因为他的表示方式能被img的src读取打印结果如下:

相信搞过前端的人都不陌生这些base64的字符串,其实就是一段能表示出来的二进制文件,至于为啥能解析成图片这里就不展开讲了,有兴趣自行百度,一堆答案

那有人又会问了FileReader.readAsDataURL 和URL.createObjectURL有啥区别呢?

FileReader.readAsDataURL 和URL.createObjectURL区别

1、返回值

  FileReader.readAsDataURL(blob)可以得到一段base64的字符串
  URL.createObjectURL(blob)得到的是当前文件的一个内存url

2、内存使用

 FileReader.readAsDataURL(blob)得到一段超长的base64的字符串,代表的是个二进制
  URL.createObjectURL(blob)得到的是一个blob开头url地址 指向的是这个二进制地址

3、内存清理

FileReader.readAsDataURL(blob)依照js垃圾回收机制自动从内存中清理
 URL.createObjectURL(blob)存在于当前document内,清除方式只有upload()事件或者revokeObjectURL手动清除

4、执行方式

FileReader.readAsDataURL(blob)通过回调的方式f返回,异步执行;
URL.createObjectURL(blob) 直接返回,同步执行;

5、多个文件

  FileReader.readAsDataURL(blob)同时处理多个文件时,需要一个文件对应一个FileReader对象;
  URL.createObjectURL(blob) 依次返回,没有影响;

更多详细区别参考:blog.csdn.net/qq_36671474…

总结

到这里啊顺利的实现一个提前预览图片的功能,核心就是利用前端的一些对象去将文件资源存存起来,不管存入内存或者字符串,然后读取即可,文章属于现学现卖,记录学习点滴,不对之处,还请大佬指正!

本文参与腾讯云自媒体分享计划,欢迎正在阅读的你也加入,一起分享。

我来说两句

0 条评论
登录 后参与评论

相关文章

  • 玩转前端图片上传

    本文讲的图片上传,主要是针对上传头像的。大家都知道,上传头像一般都会分成以下 4 个步骤:

    JowayYoung
  • 微信公众号Markdown Here排版的缺失环节

    早上看了一下微信公众号后台。我上一篇微信公众号什么时间发的?看完我自己都吓了一跳——4月15日!

    王树义
  • 你不可能知道的骨架屏玩法!

    作者曾所在我司广告事业部,广告承载方式是以刮刮卡、大转盘等活动页进行展示,然后用户参与出广告券弹层。

    秋风的笔记
  • 前端:你可能不知道的骨架屏方案设计

    作者曾所在我司广告事业部,广告承载方式是以刮刮卡、大转盘等活动页进行展示,然后用户参与出广告券弹层。

    徐小夕
  • 移动化下空间相册的挑战和应对

    十年间,PC端的空间相册已经由简单的相册功能走向多功能,移动时代,QQ 空间如何变轻,甚至跳出自己的旋律呢?来听听腾讯社交平台部从产品和技术层面的考虑。

    腾讯大讲堂
  • Android 端相机相关开发经验总结

    文主要说的是自己在做相机模块需求或者说使用 cameraview的过程中遇到了哪些问题以及相应的解决方案,最终我对 cameraview 进行了一番 enhan...

    胡家威
  • 「R」事实不等于标签:关于真假 png 的找 bug 记录

    我在日常更改 sigminer 手册后使用 knitr 生成网页文档时发现一直报错:

    王诗翔呀
  • Camera development experience on Android

    众所周知,Android平台不仅系统碎片化严重,而且不同手机的硬件配置差异导致开发某些模块的时候坑比较多,相机模块就是其中之一。为什么呢?首先,Android系...

    宅男潇涧
  • 手机Markdown写作:插图一键同步七牛图床

    通勤或者旅途中,你偶然见到的景象或者资料触动了你,让你灵光一闪,突然有了很好的创意。此时,你的电脑并不在身边。不过作为高效能人士,这点儿困难难不倒你。你立即用手...

    王树义
  • 剪切板图片粘贴上传

    在H5技术发展如火如荼的今天,前端,再也不是页面的代名词,而今的前端早已不再是写写页面写写简单的交互了,现在的前端相比十年前的前端已经发生了翻天覆地的变化,像近...

    javascript.shop
  • 干货丨通过HTTP/2实现每天处理400GB图片的实践

    如今确定下来的HTTP/2规格已经引发了web性能社区的广泛关注。新协议旨在解决老旧的HTTP/1.x协议相关的常见网络性能问题,同时还要保留老协议的现有语义。...

    CSDN技术头条
  • 从web图片裁剪出发:了解H5中的Blob

    刚开始做前端的时候,有个功能卡住我了,就是裁剪并上传头像。当时两个方案摆在我面前,一个是flash,我不会。另一个是通过iframe上传图片,然后再上传坐标由后...

    李海彬
  • Vue开发微信H5页面总结

    刚入门前端的时候写过很多的微信H5页面,时隔多年感觉应该是手到擒来,不曾想竟很是费了一些功夫。现在把本次开发过程中遇到的问题以及我是如何解决的,做个记录。防止自...

    前端黑板报
  • 公众号好看的文章配图去哪找,8个免费找图+图片滤镜特效工具了解一下!

    经常收到提问,你们都是去哪里找的公众号文章配图?大家都知道要想阅读数高,光文章好看不行,图片也很重要,在普通的新媒体?只知道去某度某狗上找图时,来吃下我这枚安利...

    LOGO设计小能手
  • 从2.9秒到0.6秒,信息流首屏提效80%的秘诀

    (文末有彩蛋~)       近两年,信息流行业处于一个增长缓慢甚至停滞的状态,包括今日头条、腾讯看点在内的信息流产品都在寻求自己的破局之路。与此同时,...

    腾讯大讲堂
  • 从输入URL到页面加载完的过程中都发生了什么事情

    一个HTTP请求的过程 为了简化我们先从一个HTTP请求开始,简要介绍一下一个HTTP求情的网络传输过程,也就是所谓的“从输入 URL 到页面下载完的过程中都发...

    前朝楚水
  • Spring Boot搭建的一个在线文件预览系统!支持ppt、doc等多种类型文件预览

    总的来说我觉得 kkFileView 是一个非常棒的开源项目,在线文件预览这个需求非常常见。感谢开源!

    Guide哥
  • Python奇淫技巧之自动登录哔哩哔哩

    嘿,各位小伙伴晚上好呀,今天要带来点什么干货呢,就从我的实际开发中来给大家带来一个案例吧,如何自动登录哔哩哔哩。

    Python进阶者
  • COSBrowser 移动端——随时随地查看管理数据

    不用着急,COSBrowser 移动端帮您解决这些问题,让您随时随地查看管理您的数据~

    云存储

扫码关注云+社区

领取腾讯云代金券