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

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

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

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

复制代码

长相如下:

955b1d56e1ae8a013252cfa49792ab6e.png

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

964e611302a495f09643320896bdb15f.png

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

b065cb50033396eb4ab0f5830dce5777.png

其实这个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类似。

c3a3a8707722a3ea5178f3d9be76acf0.png

此时一个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会发现,它们统统变成了这样的形式。

5ebc7dfe42a66327a4b53046a39754c1.png

这其实是为了防止盗链,而让后台传入的一段二进制流,我们在给包装成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解析之后指向的地址就是个二进制文件的空间地址,看不见摸不着b9938c8cfb0fedc9c7faff99b6e4922e.png

解析到此,回归正题

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

废话少说先上代码:

//html

复制代码//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)

复制代码

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

fb6038cd2554ced94a385f5633c00806.png

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

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读取打印结果如下:

4f9f8b68a11809820a3081fcf28d0d2c.png

相信搞过前端的人都不陌生这些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) 依次返回,没有影响;

复制代码

总结

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

b739ec46bb5c46d9c0aa4ce35ba1ea56.png

关于找一找教程网

本站文章仅代表作者观点,不代表本站立场,所有文章非营利性免费分享。

本站提供了软件编程、网站开发技术、服务器运维、人工智能等等IT技术文章,希望广大程序员努力学习,让我们用科技改变世界。

[面试题:我现在上传图片的时候提前预览到图片怎么办?]http://www.zyiz.net/tech/detail-118227.html

  • 0
    点赞
  • 1
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值