前端图片上传合集

图片上传是一个很常见的功能,这里将举例h5、小程序、pc端图片上传。
主要逻辑:通过图片上传组件或api拿到图片信息,上传服务器拿到服务器url

1:h5

在这里插入图片描述
这里是base64image的工具函数

function getLocalFilePath(path) {
    if (path.indexOf('_www') === 0 || path.indexOf('_doc') === 0 || path.indexOf('_documents') === 0 || path.indexOf('_downloads') === 0) {
        return path
    }
    if (path.indexOf('file://') === 0) {
        return path
    }
    if (path.indexOf('/storage/emulated/0/') === 0) {
        return path
    }
    if (path.indexOf('/') === 0) {
        var localFilePath = plus.io.convertAbsoluteFileSystem(path)
        if (localFilePath !== path) {
            return localFilePath
        } else {
            path = path.substr(1)
        }
    }
    return '_www/' + path
}

function dataUrlToBase64(str) {
    var array = str.split(',')
    return array[array.length - 1]
}

var index = 0
function getNewFileId() {
    return Date.now() + String(index++)
}

function biggerThan(v1, v2) {
    var v1Array = v1.split('.')
    var v2Array = v2.split('.')
    var update = false
    for (var index = 0; index < v2Array.length; index++) {
        var diff = v1Array[index] - v2Array[index]
        if (diff !== 0) {
            update = diff > 0
            break
        }
    }
    return update
}

export function pathToBase64(path) {
    return new Promise(function(resolve, reject) {
        if (typeof window === 'object' && 'document' in window) {
            if (typeof FileReader === 'function') {
                var xhr = new XMLHttpRequest()
                xhr.open('GET', path, true)
                xhr.responseType = 'blob'
                xhr.onload = function() {
                    if (this.status === 200) {
                        let fileReader = new FileReader()
                        fileReader.onload = function(e) {
                            resolve(e.target.result)
                        }
                        fileReader.onerror = reject
                        fileReader.readAsDataURL(this.response)
                    }
                }
                xhr.onerror = reject
                xhr.send()
                return
            }
            var canvas = document.createElement('canvas')
            var c2x = canvas.getContext('2d')
            var img = new Image
            img.onload = function() {
                canvas.width = img.width
                canvas.height = img.height
                c2x.drawImage(img, 0, 0)
                resolve(canvas.toDataURL())
                canvas.height = canvas.width = 0
            }
            img.onerror = reject
            img.src = path
            return
        }
        if (typeof plus === 'object') {
            plus.io.resolveLocalFileSystemURL(getLocalFilePath(path), function(entry) {
                entry.file(function(file) {
                    var fileReader = new plus.io.FileReader()
                    fileReader.onload = function(data) {
                        resolve(data.target.result)
                    }
                    fileReader.onerror = function(error) {
                        reject(error)
                    }
                    fileReader.readAsDataURL(file)
                }, function(error) {
                    reject(error)
                })
            }, function(error) {
                reject(error)
            })
            return
        }
        if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
            wx.getFileSystemManager().readFile({
                filePath: path,
                encoding: 'base64',
                success: function(res) {
                    resolve('data:image/png;base64,' + res.data)
                },
                fail: function(error) {
                    reject(error)
                }
            })
            return
        }
        reject(new Error('not support'))
    })
}

export function base64ToPath(base64) {
    return new Promise(function(resolve, reject) {
        if (typeof window === 'object' && 'document' in window) {
            base64 = base64.split(',')
            var type = base64[0].match(/:(.*?);/)[1]
            var str = atob(base64[1])
            var n = str.length
            var array = new Uint8Array(n)
            while (n--) {
                array[n] = str.charCodeAt(n)
            }
            return resolve((window.URL || window.webkitURL).createObjectURL(new Blob([array], { type: type })))
        }
        var extName = base64.split(',')[0].match(/data\:\S+\/(\S+);/)
        if (extName) {
            extName = extName[1]
        } else {
            reject(new Error('base64 error'))
        }
        var fileName = getNewFileId() + '.' + extName
        if (typeof plus === 'object') {
            var basePath = '_doc'
            var dirPath = 'uniapp_temp'
            var filePath = basePath + '/' + dirPath + '/' + fileName
            if (!biggerThan(plus.os.name === 'Android' ? '1.9.9.80627' : '1.9.9.80472', plus.runtime.innerVersion)) {
                plus.io.resolveLocalFileSystemURL(basePath, function(entry) {
                    entry.getDirectory(dirPath, {
                        create: true,
                        exclusive: false,
                    }, function(entry) {
                        entry.getFile(fileName, {
                            create: true,
                            exclusive: false,
                        }, function(entry) {
                            entry.createWriter(function(writer) {
                                writer.onwrite = function() {
                                    resolve(filePath)
                                }
                                writer.onerror = reject
                                writer.seek(0)
                                writer.writeAsBinary(dataUrlToBase64(base64))
                            }, reject)
                        }, reject)
                    }, reject)
                }, reject)
                return
            }
            var bitmap = new plus.nativeObj.Bitmap(fileName)
            bitmap.loadBase64Data(base64, function() {
                bitmap.save(filePath, {}, function() {
                    bitmap.clear()
                    resolve(filePath)
                }, function(error) {
                    bitmap.clear()
                    reject(error)
                })
            }, function(error) {
                bitmap.clear()
                reject(error)
            })
            return
        }
        if (typeof wx === 'object' && wx.canIUse('getFileSystemManager')) {
            var filePath = wx.env.USER_DATA_PATH + '/' + fileName
            wx.getFileSystemManager().writeFile({
                filePath: filePath,
                data: dataUrlToBase64(base64),
                encoding: 'base64',
                success: function() {
                    resolve(filePath)
                },
                fail: function(error) {
                    reject(error)
                }
            })
            return
        }
        reject(new Error('not support'))
    })
}

2.以taro小程序为例

微信小程序把chooseImage给更新成chooseMedia,将视频与图片合二为一。

在这里插入图片描述

// 不可使用promise/async异步写法
export function authSetting(scope, succFn, errFn) {
  Taro.getSetting({
    success(res) {
      const result = res.authSetting[isWeixin ? `scope.${scope}` : `${scope}`]
      if (isWeixin) {
        if (result === undefined) {
          Taro.authorize({
            scope: `scope.${scope}`
          }).then(succFn, errFn)
        } else if (!result) {
          Taro.openSetting().then(succFn, errFn)
        } else {
          succFn()
        }
      } else if (isAlipay) {
        // const alipayScope = {
        //   "album": "album",
        //   "writePhotosAlbum": "album"
        // }
        if (result === false) {
          Taro.openSetting().then(succFn, errFn)
        } else {
          succFn()
        }
      }
    },
    fail(res) {
      console.error(res)
    }
  })
}

上传图片服务器的函数

import Taro from '@tarojs/taro'
import req from '@/api/req'
import S from '@/spx'
import { isAlipay, getAppId, exceedLimit, isWeixin } from '@/utils'
// import * as qiniu from 'qiniu-js'

const getToken = (params) => {
  return req.get('espier/image_upload_token', params)
}

// const uploadURLFromRegionCode = (code) => {
//   switch(code) {
//       case 'z0': return'https://up.qiniup.com'
//       case 'z1': return 'https://up-z1.qiniup.com'
//       case 'z2': return 'https://up-z2.qiniup.com'
//       case 'na0': return 'https://up-na0.qiniup.com'
//       case 'as0': return 'https://up-as0.qiniup.com'
//       default: console.error('please make the region is with one of [z0, z1, z2, na0, as0]')
//   }
// }

const upload = {
  aliUpload: async (item, tokenRes) => {
    const { accessid, dir, host, policy, signature, filetype } = tokenRes
    const filename = item.url.slice(item.url.lastIndexOf('/') + 1)
    const updata = {
      url: host,
      filePath: item.url,
      name: 'file',
      withCredentials: false,
      formData: {
        name: filename,
        key: `${dir}`,
        policy: policy,
        OSSAccessKeyId: accessid,
        // 让服务端返回200
        signature: signature,
        success_action_status: '200'
        // 服务端回调
        // callback: callback
      },
      // fileType: 'image',
      fileType: filetype,
      header: {
        'Content-Type': 'application/x-www-form-urlencoded', // 只能是这种形式
      },
      fail: (err) => {
        // debugger
        // console.log('aliUpload:host', host)
        console.log('aliUpload:Taro.uploadFile', err)
      }
    }
    // console.log('upload:updata', updata)
    // debugger
    try {
      const res = await Taro.uploadFile(updata)
      // console.log('---aliUpload-upload:res', res)
      // console.log('---aliUpload-:dir', host, dir)
      if (!res) {
        return false
      }
      return {
        url: `${host}${dir}`,
        filetype
      }
    } catch (e) {
      throw new Error(`aliUpload:${e}`)
    }
  },
  qiNiuUpload: async (item, tokenRes) => {
    const { token, key, domain, host, filetype } = tokenRes

    const uploadFile = isAlipay ? my.uploadFile : Taro.uploadFile

    try {
      const { data } = await uploadFile({
        url: host,
        filePath: item.url,
        // fileType: 'image',
        fileType: filetype,
        withCredentials: false,
        [isAlipay ? 'fileName' : 'name']: 'file',
        formData: {
          'token': token,
          'key': key
        }
      })
      const imgData = JSON.parse(data)
      if (!imgData.key) {
        return false
      }
      return {
        url: `${domain}/${imgData.key}`,
        filetype
      }
    } catch (e) {
      console.error(e)
      throw new Error(e)
    }
  },
  localUpload: async (item, tokenRes) => {
    const { filetype, domain } = tokenRes
    const filename = item.url.slice(item.url.lastIndexOf('/') + 1)
    let header = {
      Authorization: `Bearer ${S.getAuthToken()}`,
    }
    if (isWeixin) {
      header['authorizer-appid'] = getAppId()
    }
    try {
      const res = await Taro.uploadFile({
        url: `${req.baseURL}espier/uploadlocal`,
        filePath: item.url,
        header,
        withCredentials: false,
        name: 'images',
        formData: {
          name: filename,
          filetype
        }
      })
      const data = JSON.parse(res.data)
      const { image_url } = data.data
      if (!image_url) {
        return false
      }
      return {
        url: `${domain}/${image_url}`,
        filetype
      }
    } catch (e) {
      throw new Error(e)
    }
  },
  awsUpload: async (item, tokenRes) => {
    const {
      formInputs = {
        XAmzCredential: '',
        XAmzAlgorithm: '',
        XAmzDate: '',
        Policy: '',
        XAmzSignature: '',
        key: ''
      },
      formAttributes = {
        action: ''
      },
      filetype
    } = tokenRes
    try {
      const res = await Taro.uploadFile({
        url: formAttributes.action,
        filePath: item.url,
        name: 'file',
        formData: {
          key: formInputs.key,
          'X-Amz-Credential': formInputs.XAmzCredential,
          'X-Amz-Algorithm': `AES256`,
          Policy: formInputs.Policy,
          'X-Amz-Algorithm': formInputs.XAmzAlgorithm,
          'X-Amz-Date': formInputs.XAmzDate,
          'X-Amz-Signature': formInputs.XAmzSignature
        }
      })

      const { Location } = res.header
      if (!Location) {
        return false
      }
      return {
        url: Location,
        filetype,
        thumb: item.thumb
      }
    } catch (e) {
      throw new Error(e)
    }
  }
}

const getUploadFun = (dirver) => {
  switch (dirver) {
    case 'oss':
      return 'aliUpload'
    case 'local':
      return 'localUpload'
    case 'aws':
      return 'awsUpload'
    default:
      return 'qiNiuUpload'
  }
}

// 返回对应上传方式
const uploadImageFn = async (imgFiles, filetype = 'image') => {
  console.log('---imgFiles---', imgFiles)
  const imgs = []
  for (const item of imgFiles) {
    if (!item.file) {
      if (item.url) {
        imgs.push(item)
      }
      continue
    }
    if (exceedLimit(item.file)) {
      Taro.showToast({
        title: '文件大小超出最大限制,请压缩后再上传',
        icon: 'none'
      })
      break
    }
    try {
      const filename = item.url.slice(item.url.lastIndexOf('/') + 1)
      const { driver, token } = await getToken({ filetype, filename })
      const uploadType = getUploadFun(driver)
      // console.log('----uploadType----', uploadType)
      let img = await upload[uploadType](item, { ...token, filetype: item.fileType || filetype })
      if (filetype == 'videos' && item.thumb) {
        const _thumb = {
          url: item.thumb
        }
        const thumbFileName = _thumb.url.slice(_thumb.url.lastIndexOf('/') + 1)
        const thumbRes = await getToken({ filetype: 'image', filename: thumbFileName })
        const thumbUploadType = getUploadFun(thumbRes.driver)

        const thumbImg = await upload[thumbUploadType]({ url: _thumb.url }, { ...thumbRes.token, filetype: 'image' })
        if(thumbImg) {
          img['thumb'] = thumbImg.url
        }
      }
      console.log('---uploadImageFn---', img)
      if (!img || !img.url) {
        continue
      }
      imgs.push(img)
    } catch (err) {
      console.error('---uploadImageFn---', err.message)
    }
  }
  // console.log('---uploadImageFn---2', imgs)
  return imgs
}

export default {
  uploadImageFn
}

3:pc后台

直接上elementui就行,拿到图片信息上传服务器即可
https://element.eleme.cn/#/zh-CN/component/upload#yong-hu-tou-xiang-shang-chuan

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

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

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

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值