Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

原生实现上传文件预览 #46

Open
18888628835 opened this issue Jun 13, 2021 · 0 comments
Open

原生实现上传文件预览 #46

18888628835 opened this issue Jun 13, 2021 · 0 comments

Comments

@18888628835
Copy link
Owner

18888628835 commented Jun 13, 2021

原生实现上传文件预览

获取上传文件信息

原生的HTML5通过<input type="file" >属性来上传文件,我们可以采用浏览器提供的 File API 对所选择的文件进行操控。

如果我们希望访问选择的文件,分为两步

  • 获取 DOM 元素
<input type="file" id="input">
const selectFile = document.getElementById('input')
  • 监控 change 事件
const selectFile = document.getElementById('input')
selectFile.addEventListener('change',()=>{
  console.log(selectFile.files)
})

通过 DOM 的 files属性,我们可以得知上传文件的相关信息,比如图中的文件名(name)和大小(size)
image
浏览器直接将上传文件存到 fileList 这个数据结构中,这个数据结构可以存很多个文件,如果想要存多个,那么就需要添加 html 属性multiple

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

难看的上传文件控件

上传文件的控件实在很丑,我们有很多种方法改变它,这里就介绍最常用也是最简单的方式。

第一步,隐藏 input 控件

#input{
  display:none;
}

第二步,创建好看的点击区域,这里就用 button 控件吧

  <button>上传</button>
const selectFile = document.getElementById('input')
const button=document.querySelector('button') /

selectFile.addEventListener('change',()=>{
  console.log(selectFile.files)
})

button.onclick=function (){
  selectFile.click() // 调用 click函数点击
}

现在只需要对 button 组件进行样式调整就行啦。

使用 FileReader 对象预览上传的图片

下面,我们需要做一个预览图片的小功能,还是使用上面的代码,不过这里添加一个新的预览区.

我们考虑使用FileReader对象让浏览器异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容。

  <div>
    <input type="file" multiple id="input">
  </div>
  <button>上传</button>
  <img class='preview' />
#input{
  display:none;
}
.preview{
  width:100px;
  height:100px
}
const selectFile = document.getElementById('input')
const button = document.querySelector('button')
const preview = document.querySelector('.preview')

selectFile.addEventListener('change', () => {
  //循环读取 fileList 的file
  for (let file of selectFile.files) {
    const imageReg = /image\//g //正则表达式
   // 检测 file 的 type 属性能否匹配到"image/"
    if (!imageReg.test(file.type)) {
      break
    }
    // 这里用到 FileReader API创建一个 Reader 读取器
    let reader = new FileReader()
    //当 reader 对某文件读取成功后的回调
    reader.onload = function (e){
      preview.src=e.target.result
    }
    //读取 DataURL后触发onload 回调
    reader.readAsDataURL(file);
  }
})

button.onclick = function() {
  selectFile.click()
}

上面代码中readAsDataURL 方法会读取指定的 BlobFile 对象。

读取操作完成的时候,readyState会变成已完成DONE,并触发 loadend (en-US) 事件,同时 result 属性将包含一个data:URL格式的字符串(base64编码)以表示所读取文件的内容。

我们把这个 base64编码放到创建好的 img 标签的 src 属性上,就可以完成图片的预览。

使用 createObjectURL预览上传的图片

这个 API 跟readAsDataURL的效果差不多,不过它返回的不是base64编码,而是DOMString,我们可以理解为本地内存容器的URL地址。

只需要稍微修改一下代码就可以了

const selectFile = document.getElementById('input')
const button = document.querySelector('button')
const preview = document.querySelector('.preview')

selectFile.addEventListener('change', () => {
  //循环读取 fileList 的file
  for (let file of selectFile.files) {
    const imageReg = /image\//g //正则表达式
      // 检测 file 的 type 属性能否匹配到"image/"
    if (!imageReg.test(file.type)) {
      break
    }
    // 这里用到 createObjectURL API生成本地内存 url
    preview.src = window.URL.createObjectURL(file)
    preview.onload = function() {
      //由于每次使用createObjectURL都会产生一个URL 对象。
      //当你结束使用某个 URL 对象之后,应该通过调用这个方法来让浏览器知道不用在内存中继续保留对这个文件的引用了。
      window.URL.revokeObjectURL(this.src)
    }
  }
})

button.onclick = function() {
  selectFile.click()
}

预览 PDF

createObjectURL还可以用来生成 PDF 预览,我们可以采用 iframe 标签,让 pdf 展示在 iframe 上

  <iframe id='viewer'></iframe>
#viewer{
  width:600px;
  height:600px;
  border:1px solid red;
}
selectFile.addEventListener('change', () => {
  //循环读取 fileList 的file
  for (let file of selectFile.files) {
    const obj_url=window.URL.createObjectURL(file)
    // 这里用到 createObjectURL API生成本地内存 url
    iframe.setAttribute('src', obj_url);
    window.URL.revokeObjectURL(obj_url);
  }
})

先介绍这三种比较广泛的预览形式,后续如有需要,我再补充~

enjoy!

@18888628835 18888628835 changed the title JS 上传文件预览功能原理 原生实现上传文件预览 Jun 17, 2021
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Labels
None yet
Projects
None yet
Development

No branches or pull requests

1 participant