发布时间:2023-05-18 文章分类:WEB开发, 电脑百科 投稿人:李佳 字号: 默认 | | 超大 打印

也是在最近一点时间写小demo 遇到的一些问题

比如在用户界面,用户选择本地的一张照片,前端把照片传到后端,后端怎么把照片保存到服务器,然后返回给 图片线上地址。也是找了一些文章,然后分享下。 

技术

前端:react

后端:egg.js(node框架)

base64 转换 

转二进制 保存图片

base64(mdn)

Base64 是一组相似的二进制到文本(binary-to-text)的编码规则,使得二进制数据在解释成 radix-64 的表现形式后能够用 ASCII 字符串的格式表示出来。Base64 这个词出自一种 MIME 数据传输编码。

Base64 编码普遍应用于需要通过被设计为处理文本数据的媒介上储存和传输二进制数据而需要编码该二进制数据的场景。这样是为了保证数据的完整并且不用在传输过程中修改这些数据。Base64 也被一些应用(包括使用 MIME 的电子邮件)和在 XML 中储存复杂数据时使用。

为什么转成base64&好处

获取文件的base64格式

<!-- 我这里写个简单的样式 -->
<input type="file">
<button>提交</button>

 选择一张图片文件,然后点击提交按钮我们就会得到一个 base64字符串

  const files = document.querySelector('input[type=file]')
  const btn = document.querySelector('button')
  btn.addEventListener('click', function () {
     var reader = new FileReader();
     reader.readAsDataURL(files.files[0]);
     reader.onloadend = function () {
         var base64 = reader.result;
         console.log(base64);
     }
  })

console:

 我们可以通过这个 base64 格式的字符串,直接复制到浏览器的地址上,就能访问图片

data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAEgAAABICAMAAABiM0N1AAAABGdBTUEAALGPC/xhBQAAAAFzUkdCAK7OHOkAAADMUExURUdwTPn5+/j4/Pn5+/n5/Pn5+/n5+/n5+/j4+/n5+vv7+/j4+/n5+vv7+/n5+/j4+/j4+vn5+vn5/Pj4+/r6+vr6/Pn5+/n5+/r6+vr6/Pn5+/j4+vj4+gAAAPHx8wcHB0ZGRkdHSLS0trOztbKytLGxs2NjZAYGBkxMTfPz9dHR0pCQkggICPb2+F5eX2JiYxoaGkZGR4+PkdLS093d38jIyQkJCUtLTDc3N7W1t9PT1I2Nj2LkZLoAAAAkdFJOUwD+IpKwVQT57P1y0kIM58w8BvB03wjRW7kzYoka7wJtZbFuA8zxGUAAAAIESURBVFjDrZjpdoIwEIWjoIC7goJQ1w7a1ta6dt/7/u/UKNrWhWSCc/8y5ztAMncWxuLVbvqB3nBMwzCdhh74zTZLoLOO3oI9tfTOmRql7noWHJXluXU0pmiXQKCSXURhsjkTJDJzWTmnkgeE8hUJpqqlAKWUVhVx0mVAq5yO5xRqoKBaIY6TMUBJRuY4p2uBoqzu0fdR5nDSkXcqGJBAxsF/StcgkWp7Z1ctQ0KVd++TBoml7eRFKjko9S9bsnk4Qfm/DM7BScr9+o95Gsjc+pMNJ8re+KrID19eB3JQKXJfNz5ieReGD59ykrsGefEB85BrOJKCvHXdESTrJMSRrFWV6gsCxiGS1OGgnuD582JDupKAdF6XW6KA0RBHarVZUxxxjSQ1mQ8kJJ8FQEIKmA4kJJ015Pf25lZOajAH8KTFLDbEYSgL2ZLu462EoarQ4CMCvcfXJRRocBlxwm8ByFTgXEwFn+YocAQe58iPH8Xhx6+TcPiFDEg4PEV8Eg5PWqGNTLEcbiNCY5tjOdzYhFY7QXJWVoswfzlnbf6icjR745xHOWddjkQFEr7Gk6elPIk8WcnGypU3EShtmgiytoau0SJr/eiaUbL2mK5hpxshyIYaujGLbvCjG0XphmO6cZ1ugUC30qBbshCufegWUYSrsWhZ1+8dLut6qsu6SOcq68Mf88U7H+osen4AAAAASUVORK5CYII=

这串字符串其实就是一张照片的DataURL,就是利用base64编码把图片数据翻译成标准ASCII字符。也可以把这个字符串直接放到 img 标签 src 上。这样也可以节省 http网络的一次请求

字符串的结构:

data:image/png;base64          声明数据协议及类型名称

base64                                    编码形式为base64

iVBORw0KGgoAAAA...           内容

 接下来我们开始完整的演示文件上传的过程

前端: react(就是转base64,上面已经讲到)

后端:egg.js(node)

前端

 

 图片上传流程&前端上传文件&后端保存文件&并返回图片地址

 很简单的样式,我这里做了一个回显的效果就是获取完 图片的 base64 字符串然后 在赋值给img

//react
 const fileRef = useRef(0)
 const [ src, setSrc] = useState()
 <img src={src} alt=""/>
 <input type="file" name="" id="" ref={fileRef} onChange={(e) => fileBtn(e)}/>

函数  filebtn

function fileBtn(e){
        var imgfile = e.target.files[0] //获取文件信息
        var reader = new FileReader();
        reader.onload=function(){
            var fileurl = reader.result
            setSrc(fileurl) // 这个 useState 把获取的base64 给到img 的src 上
            // 这里有一个向后端发送的请求
            postimg({
                files: fileurl
            }).then(res=>{
                console.log(res);
            })
        }
        reader.readAsDataURL(imgfile)
 }

postimg 这里是封装的一个请求 http 是一个 axios(网上封装好的)(请求需要用 post

function postimg(params){
    return new Promise((resolve,reject)=>{
        http('post','postimg',params).then(res=>{
            resolve(res)
        },error =>{
            console.log("网络异常~", error);
            reject(error)
        })
    })
}

 到这里前端部分就已经实现完毕了

后端

 首先在router 文件里编写路由

router.post('/postimg', controller.home.postimg);

然后在controller 文件下 home 文件 里面的 postimg(这里强调下要用post 请求

我们这里是用了一个中间件(方便我们获取 参数,不需要考虑 get 或者是 post)

  params(key) {
    const method = this.request.method;
    if (method === 'GET') {
      return key ? this.query[key] : this.query;
    }
    return key ? this.request.body[key] : this.request.body;
  },
 async postimg() {
    const { ctx } = this;
    const file = ctx.params().files; // 获取参数
    const imgtype = file.match(/data:image\/(png|jpep|jpg|JPG|gif|webp);/)[1];//获取文件的类型
    const filename = `${Math.floor(Math.random() * 10000000000)}.${imgtype}`;//获取随机数
    const publi = `//${ctx.request.header.host}/public/updataImg/${filename}`; //返回的 文件路径
    const filepath = path.join(`${__dirname}/../public`, `updataImg/${filename}`);//写入文件的路径
    const fileBuffer = Buffer.from(file.replace(/^data:image\/(png|jpep|jpg|gif|webp);base64,/, ''), 'base64'); //讲base64 的 data:image/png;base64 去掉,并转成而二进制
    console.log(publi, 123);
    fs.writeFileSync(filepath, fileBuffer); //写入文件
  }

我这是用 egg 来写的,如果用express或者koa 搭建的服务器,原理也是一样,复制粘贴即可。