图片拍照上传解决方案

2017-08-10  本文已影响1362人  回调的幸福时光

前言

图片上传是常见的需求之一,本文讲解自己的解决过程,以及遇到坑。

调用摄像头

 <input type="file" accept="image/*" capture name="" value="">

微信内置浏览器,和一些主流浏览器支持调用摄像头,但也有很多不支持调用摄像头,仅支持相册。
如果是WebView中,就需要客户端支持了,android和ios的权限也是问题。

formData方式

formData简介

简单的说就是:通过formData,我们可以用ajax方式来发送表单数据;以前上传图片是需要用form表单提交的。

界面部分

我们知道浏览器默认显示的文件上传按钮是很丑的,通常UI都会对上传按钮进行设计。有以下几种方案来写样式。

<div class="upload-wrapper">
      upload
      <input type="file" name="upload" multiple="multiple" accept="image/*" value="">
    </div>
.upload-wrapper {
  position: relative;
  box-sizing: border-box;
  overflow: hidden;
  width: 100px;
  height: 40px;
  line-height: 40px;
  text-align: center;
  border-radius: 5px;
  border: 1px solid pink;
  background: #fff;
}
.upload-wrapper:hover {
  background: pink;
  color: #fff;
}
input[type="file"] {
  box-sizing: border-box;
  opacity: 0;
  width: 100%;
  height: 100%;
  position: absolute;
  top: 0;
  left: 0;
}
upload-1.png

弊端:

upload-2.png

 <div class="upload-wrapper" @click="upload('logo_path')">
      upload
      <input ref="logo_path" type="file" name="logo_path" multiple="multiple" accept="image/*" value="" @change="selectImg('logo_path')">
    </div>
  .upload-wrapper {
  box-sizing: border-box;
  overflow: hidden;
  width: 100px;
  height: 40px;
  line-height: 40px;
  text-align: center;
  border-radius: 5px;
  border: 1px solid pink;
  background: #fff;
  cursor: pointer;
}
.upload-wrapper:hover {
  background: pink;
  color: #fff;
}
/* pc端 */
input[type="file"] {
  display: none;
}
/* 移动端 */
input[type="file"] {
  width: 0;
  height: 0;
  z-index: -1;
}

通过ref获取上传按钮。

/**
* 触发上传
*/
upload: function (name) {
  this.$refs[name].click()   // 触发了selectImg函数
},

上传过程

selectImg: function (name) {
    // 获取文件
    ...
    // 校验
    ...
    // formData
    ...
}
获取文件

ref方式

   let file = this.$refs[name].files[0]

event.target方式

 /**
   * 获取图片
   */
  function getImg (files) {
    var file;
    if (files && files.length > 0) {
      file = files[0];
    }
    return file;
  }
校验
function verifyImg(file) {
  // 空
  if (!file) {
    return false
  }
  // 图片格式
  if (!/\/(?:jpeg|png|jpg|bmp)/i.test(file.type)) {
      // 提示操作
       return false
   }
  // 图片大小
   if (file.size > 5 * 1024 * 1024) {
        // 提示操作
       return false
   }
}
formData

坑:

let formData = new FormData()
formData.append('UploadForm[image]', file)
let that = this
axios.post(url, formData)
     .then(function (res) {
     // success
   })
   .catch(function (error) {
       console.log(error)
   })

图片预览

FileReader

FileReader简介

通过readAsDataURL(),在读取操作完成后,result属性中将包含一个data:URL格式的字符串以表示所读取文件的内容。

if (window.FileReader) {
    let fr = new FileReader()
    let that = this
    fr.readAsDataURL(file)
    fr.onloadend = function (e) {
       that.imgUrl = e.target.result
    }
 }

base64字符串

    /**
     * 将图片转化成base64字符串,并上传
     */
    function base64(file) {
      if (window.FileReader) {
        var fr = new FileReader();
        fr.readAsDataURL(file);
        fr.onloadend = function (e) {
          var params = e.target.result;
          // 以下是去掉data协议
          // params = params.replace("data:image/jpeg;base64,", "") 
        }
      }
    }

兼容性

我在safari中测试,发现是支持的。

support.png
URL.createObjectURL()

URL.createObjectURL简介

通过URL.createObjectURL()创建一个URL对象,这个URL对象表示指定的file对象或Blob对象。

this.imgUrl = window.URL.createObjectURL(file)

兼容性

support.png

canvas压缩图片

张鑫旭的文章:HTML5 file API加canvas实现图片前端JS压缩并上传

数据类型

张鑫旭的文章:理解DOMString、Document、FormData、Blob、File、ArrayBuffer数据类型

参考

使用Camera API
张鑫旭

上一篇 下一篇

猜你喜欢

热点阅读