美文网首页
图片拍照上传解决方案

图片拍照上传解决方案

作者: 回调的幸福时光 | 来源:发表于2017-08-10 14:18 被阅读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

弊端:

  • 样式复杂,涉及定位
  • cursor设置pointer无效
    • 为保证点击上传按钮时,文件窗口弹出,这里是通过事件冒泡起作用的。
    • 真正的input type="file"由两部分组成,左边的按钮,右边的提示部分;实际上当鼠标在左边的按钮上时,cursor不起作用
  • 总会提示title "未选择任何文件"
upload-2.png
  • 方案二
    input type="file"隐藏,当点击外部容器时,模拟点击上传按钮。

  • 在pc端模拟点击暂时没有发现异常
  • 在移动端模拟点击会出现两个问题
    • 事件冒泡
      点击外部容器 --> 触发模拟点击上传按钮 --> 触发事件冒泡 --> 点击外部容器,导致两个事件递归了。
    • 触发无效
      当阻止冒泡事件后,确实触发了点击,log不会打印出来,文件窗口不会弹出来;此时切换到pc,发现log打印出来,并且之前的log也打印出来了,文件窗口弹出。
 <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

坑:

  • formData.append(key, value)
    key的设置要和后端沟通好。
  • 使用axios的时候,不需要设置contentType
    我设置multipart/form-data,反而不行,谨记!!!
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
张鑫旭

相关文章

  • 图片拍照上传解决方案

    前言 图片上传是常见的需求之一,本文讲解自己的解决过程,以及遇到坑。 调用摄像头 微信内置浏览器,和一些主流浏览器...

  • Vue上传图片压缩的问题

    上传图片太大,需要前台进行图片压缩上传图片大于100* 1024 的用canvas 来压缩来解决然后IOS拍照上传...

  • vue 图片压缩

    vue 图片压缩 上传图片大于100* 1024 的用canvas 来压缩来解决 然后IOS拍照上传会有图片旋转的...

  • vue 图片压缩

    vue 图片压缩 上传图片大于100* 1024 的用canvas来压缩来解决 然后IOS拍照上传会有图片旋转的问...

  • 从相册、拍照、比例压缩、图片上传

    首先的从相册或拍照获取到图片 拍照获取图片 拍照获取到图片后通过压缩然后上传服务器 服务器会返回一张图片的URL ...

  • Android 上传图片OOM

    一个需求需要拍照上传图片到服务器,在上传图片的时候出现OOM异常,“java.lang.OutOfMemoryEr...

  • Android图片选择框架

    支持图库选择和拍照的图片选择框架 之前在android的学习过程中,用了几次图片上传,其中就使用了图片选择和拍照返...

  • WKWebview与app本地的交互框架构建

    1:场景网页需要调用本地的拍照、上传图片、保存图片、音视频的上传、图片的预览等;网页通过本地处理alert的提示框...

  • Android 从相册选取图片,拍照、裁剪一篇就够了

    开篇   基于我们开App发过程中经常要选择图片(或拍照)并裁剪做为头像上传到服务器,我把选取图片、拍照、裁剪图片...

  • 小程序上传头像 uni

    上传头像方式有三种,相册、拍照和默认图片html js

网友评论

      本文标题:图片拍照上传解决方案

      本文链接:https://www.haomeiwen.com/subject/clocrxtx.html