后台管理系统实现截图上传功能

后台管理系统实现截图上传功能

最近在工作中遇到一个需求,要求上传图片时,支持第三方截图功能,也就是我们常说的( QQ,微信截图)

分析流程

  1. 如何获取剪贴板的内容
  2. 是否有对应的组件使用
  3. 怎样获得阿里云的签名;
  4. 获得阿里云签名以后再次上传;
  5. 组件传值;

如何获取剪贴板的内容

再百度,以及观看antd组件的源码,以及观看项目以前的图片上传以后,发现可以使用onPaste获得剪贴板的内容
这次主要使用原生加react-hook

// 在return中准备一个textarea
<textarea id="text" onPaste={handelePaste} className={styles.CopyInput}></textarea>;
//className只是用来控制输入框的大小
//获得图片以后还需要准备一个img用来显示图片
<img src={ImgUrlShow} id="imgNode" style={{width:'180px',height:'180px'}}/>
//此处的src定义了一个可变的地址链接,这个后面会说到,别着急

接下来咱们看handelePaste函数中的代码

  function handelePaste (event) {
      var isChrome = false;
      if (event.clipboardData || event.originalEvent) {
        //某些chrome版本使用的是event.originalEvent
        var clipboardData = (event.clipboardData || event.originalEvent.clipboardData);
        if(clipboardData.items){
            // for chrome
            var   items = clipboardData.items,
                  len = items.length,
                  blob = null;
                  isChrome = true;
            for (var i = 0; i < len; i++) {
                if (items[i].type.indexOf("image") !== -1) {
                    //getAsFile() 此方法只是living standard firefox ie11 并不支持
                    blob = items[i].getAsFile();
                }
            }
        }
    }
  }
  //上面的代码片段就是获取剪贴板的核心代码块了,blob就是你拿到的文件了,可以打印看一下

是否有合适的组件使用

想啥呢小老弟,肯定是没有(如果你发现了,请偷偷告诉我)

获得阿里云的签名

下面就来展示获得阿里云签名的方法,敲黑板了,下面我用到的是后端直接给的接口,然后封装后方法,所以同学们,不要牛角尖哦

  //前面我们已经拿到
   function handelePaste (event) {
      var isChrome = false;
      if (event.clipboardData || event.originalEvent) {
        //某些chrome版本使用的是event.originalEvent
        var clipboardData = (event.clipboardData || event.originalEvent.clipboardData);
        if(clipboardData.items){
            // for chrome
            var   items = clipboardData.items,
                  len = items.length,
                  blob = null;
                  isChrome = true;
            for (var i = 0; i < len; i++) {
                if (items[i].type.indexOf("image") !== -1) {
                    //getAsFile() 此方法只是living standard firefox ie11 并不支持
                    blob = items[i].getAsFile();
                }
            }
            //注意我要加代码了
            if((blob!==null){
              //下面这句,不懂就打印一下,就是截取字符串
               const _file = blob.name.split('.');
               //这里我们整合一下获取签名所需要的传参(参数根据你们的接口来,切忌直接搬运)
              let params = {
                dir: '项目名称', //这个地方需要写入你的项目名称
                fileName: `nrfile${Date.now()}${Math.ceil(Math.random() * 10000)}`,
                suffix: _file[1]
              }
              //这里就是封装的请求方法了,切记不要牛角尖
              filaAutograph(params).then(res => {
                   console.log(res,78798797)
                   //这里是我为了下一个接口准备的参数(根据各自的接口来,切忌直接搬运)
                   let OSSData ={
                    key:res.data.host + res.data.dir,
                    OSSAccessKeyId: res.data.accessid,
                    policy: res.data.policy,
                    Signature: res.data.signature,
                    success_action_status: "200",
                    file:blob  //这个file传过去就是file: (binary)
                  }
            }
        }
    }
  }

再次上传阿里云

再这里问题就来了,我再这里遇到一个请求头的问题
就是fromData没有数据
下面是以解决的代码了

  //前面我们已经拿到
   function handelePaste (event) {
      var isChrome = false;
      if (event.clipboardData || event.originalEvent) {
        //某些chrome版本使用的是event.originalEvent
        var clipboardData = (event.clipboardData || event.originalEvent.clipboardData);
        if(clipboardData.items){
            // for chrome
            var   items = clipboardData.items,
                  len = items.length,
                  blob = null;
                  isChrome = true;
            for (var i = 0; i < len; i++) {
                if (items[i].type.indexOf("image") !== -1) {
                    //getAsFile() 此方法只是living standard firefox ie11 并不支持
                    blob = items[i].getAsFile();
                }
            }
            //注意我要加代码了
            if((blob!==null){
              //下面这句,不懂就打印一下,就是截取字符串
               const _file = blob.name.split('.');
               //这里我们整合一下获取签名所需要的传参(参数根据你们的接口来,切忌直接搬运)
              let params = {
                dir: 'ade-admin-html',
                fileName: `nrfile${Date.now()}${Math.ceil(Math.random() * 10000)}`,
                suffix: _file[1]
              }
              //这里就是封装的请求方法了,切记不要牛角尖
              filaAutograph(params).then(res => {
                   console.log(res,78798797)
                   //这里是我为了下一个接口准备的参数(根据各自的接口来,切忌直接搬运)
                   let OSSData ={
                    key:res.data.host + res.data.dir,
                    OSSAccessKeyId: res.data.accessid,
                    policy: res.data.policy,
                    Signature: res.data.signature,
                    success_action_status: "200",
                    file:blob  //这个file传过去就是file: (binary)
                  }
            })
            //敲黑板,我又要加代码了(参数根据各自的接口来,切忌直接搬运)
            const filename = Date.now() + ''+Math.ceil(Math.random() * 10000) + suffix;
                  //let imgUrlg = OSSData.host + '/' + OSSData.key +'/' + filename;
                  //用到上面准备的参数了,注意看哈
                  let Queryparams = {
                    name: filename,
                    OSSAccessKeyId: OSSData.OSSAccessKeyId,
                    policy: OSSData.policy,
                    signature: OSSData.Signature,
                    // expire: OSSData.expire,
                    key: OSSData.key
                    success_action_status: '200',
                    file: blob
                  };
                  //这里我们用便利的方法,把它全部加到formData 里面去
                   const formData = new FormData()
                   //new这是一个实例对象
                  Object.keys(Queryparams).forEach(key => {
                    formData.append(key,Queryparams[key])
                  })
                  //说一下,这里我们为什么用axios直接请求,不经过拦截器了,原因很简单,我们项目里的拦截器不支持我请求这个接口
                  Axios({
                    method:'post',
                    url:'https://image.newrank.cn/',//这里根据你们后端提供的接口来
                    data:formData,
                    headers:{
                      'Content-Type': 'multipart/form-data'
                    }
                  }).then(res => {
                    console.log(res,22222)
                  })
        }
    }
  }

基本上到这里就全剧终了
但是!!!
有的同学肯定会说,我不需要你这些参数,我上传base64就好了。放心,这一点也给你安排上

  //前面我们已经拿到
   function handelePaste (event) {
      var isChrome = false;
      if (event.clipboardData || event.originalEvent) {
        //某些chrome版本使用的是event.originalEvent
        var clipboardData = (event.clipboardData || event.originalEvent.clipboardData);
        if(clipboardData.items){
            // for chrome
            var   items = clipboardData.items,
                  len = items.length,
                  blob = null;
                  isChrome = true;
            for (var i = 0; i < len; i++) {
                if (items[i].type.indexOf("image") !== -1) {
                    //getAsFile() 此方法只是living standard firefox ie11 并不支持
                    blob = items[i].getAsFile();
                }
            }
            //注意我要加代码了
            if((blob!==null){
              //这里是全新版本
              //下面这一句是直接给了你一个blob对象显示图片的地址
              var blobUrl=URL.createObjectURL(blob);
               setImgUrl(blobUrl)
              var reader = new FileReader();
              //   //base64码显示
               reader.onload = function (event) {
                    // event.target.result 即为图片的Base64编码字符串
                  // console.log(event.target.result,'******')
                  //可以在这里写请求
                }
                reader.readAsDataURL(blob);
             
        }
    }
  }

跨域问题

当然也用同学们会遇到跨域的问题,因为咱们这个毕竟没有用antd的组件
所以这个时候怎么办呢???
别担心,坑我都帮你们爬过了!!!
1.代理跨域,没用
2.公司阿里云允许所有请求方式,这也没用
3.肯定有人会说,哈哈,白天写BUG了吧
害,谁让我菜呢
看到这里的孩子们,一定焦头烂额了,所以来吧看代码
博客设置页面,选择一款你喜欢的代码片高亮样式,下面展示同样高亮的 代码片.

// An highlighted block
import React from "react";
import {Input} from "antd";
// import { getUploadImage } from '@/services/adUserManage';
import styles from './index.less'
import Axios from "axios";
 
const ImageCopy = (props ={}) => {
     console.log(props)
     //这里是从父组件拿到的一些状态逻辑,和图片地址,还要函数
     //主要是用来点击切换什么的
     //这里的初始值 handleAgain === true  ---- ImgUrlShow === undefined ,changeshowImg函数
    let { handleAgain,changeshowImg,ImgUrlShow } = props
    console.log(456789,imgUrl)
    function handelePaste (event) {
      var isChrome = false;
      if (event.clipboardData || event.originalEvent) {
        //某些chrome版本使用的是event.originalEvent
        var clipboardData = (event.clipboardData || event.originalEvent.clipboardData);
        if(clipboardData.items){
            // for chrome
            var   items = clipboardData.items,
                  len = items.length,
                  blob = null;
                  isChrome = true;
            for (var i = 0; i < len; i++) {
                if (items[i].type.indexOf("image") !== -1) {
                    //getAsFile() 此方法只是living standard firefox ie11 并不支持
                    blob = items[i].getAsFile();
                }
            }
            if(blob!==null){
              const url = '接口地址' //这里建议配置一个测试,生产这样的一个请求环境
              const formData = new FormData()
              formData.append("file", blob);
              Axios({
                method:'post',
                url:url,
                data:formData,
                headers:{
                  'Content-Type': 'multipart/form-data'
                }
              }).then(res => {
                //子组件调用了父组件的方法,然后在给父组件传值
                //传的是图片地址
                 changeshowImg(res.data.value.data)
              })            
            }
        
        }
    }
  }
   return (
      <div className={styles.CopyUploadComponent}>
      //不要纠结这里的几个判断,如果你没有点击切换的功能,可以删去,如果你需要,也要仔细看过之后,再使用
            {  
           
           ImgUrlShow !== undefined && handleAgain !== false ? <img src={ImgUrlShow} id="imgNode" style={{width:'180px',height:'180px'}}/>
                :<textarea id="text" onPaste={handelePaste} className={styles.CopyInput}></textarea>
               
                     
            }
            
           
      </div>
   )
}

export default ImageCopy

上面这部分是后端重写了一个接口,只需要上传file: (binary),
因为咱们第一步直接拿的就是文件,所以不需要转化,直接传

上面这些问题就是我在工作中遇到的,可能不太适合你们,但是基本上是这个思路,其实还有很多细致的地方,这里没说到,等我下次有时间再来更新吧

还有一个问题

要是跨域解决不了,就直接找后端给你新接口
不足的地方,请各位大佬指出

  • 27
    点赞
  • 9
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值