上传图片以及使用canvas压缩图片

本文详细介绍如何使用HTML的input[type=file]上传图片,并利用FileReader读取图片为base64格式,进而通过canvas进行图片压缩。此外,还介绍了如何将压缩后的图片通过FormData上传至服务器。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

用input[‘file’]上传文件并设置类型为图片

<input type="file" id="personFile" accept='image/*' @change="upload">

在上传头像的时候,首先要把type设置为file,表示这个input是用来实现上传图片功能的,再把accept设置为’image/*’,这样就只能上传图片
在这里插入图片描述

<input type="file" id="personFile" accept='image/*' @change="upload">

因为他的样式不好改变,因此我们可以用一个div盒子把input框包住,然后把input的opacity设置为0,再给div盒子设置宽高和背景以及初始图片

<div id="personImg">
            <input type="file" id="personFile" accept='image/*' @change="upload">
</div>
#person #personFile{
    width: 100%;
    height: 100%;
    margin:0;
    border-radius: 50%;
    padding: 0;
    cursor: pointer;
    opacity:0;
  }
  #personImg{
    margin-left:20px;
    width: 82px;
    height: 82px;
    border-radius: 50%; 
    background: url('../../../../../static/2/add.png') no-repeat center;
    background-size: 'auto 100%';
    box-shadow: 0 2px 4px rgba(0, 0, 0, .12), 0 0 6px rgba(0, 0, 0, .04);
  }

利用FileReader的readAsDataURL读取图片将其转为base64

在学习这个功能之前,我们首先来了解一下Blob对象和FileReader对象

Blob 对象表示一个不可变、原始数据的类文件对象。Blob 表示的不一定是JavaScript原生格式的数据。File 接口基于Blob,继承了 blob 的功能并将其扩展使其支持用户系统上的文件。

FileReader 对象允许Web应用程序异步读取存储在用户计算机上的文件(或原始数据缓冲区)的内容,使用 FileBlob对象指定要读取的文件或数据。

  • FileReader.onload
    处理load事件。该事件在读取操作完成时触发。
  • FileReader.result只读
    文件的内容。该属性仅在读取操作完成后才有效,数据的格式取决于使用哪个方法来启动读取操作

读取方法

  • FileReader.abort()
    中止读取操作。在返回时,readyState属性为DONE。
  • FileReader.readAsArrayBuffer()
    开始读取指定的 Blob中的内容, 一旦完成, result 属性中保存的将是被读取文件的 ArrayBuffer 数据对象.
  • FileReader.readAsBinaryString()
    开始读取指定的Blob中的内容。一旦完成,result属性中将包含所读取文件的原始二进制数据。
  • FileReader.readAsDataURL()
    开始读取指定的Blob中的内容。一旦完成,result属性中将包含一个data: URL格式的字符串以表示所读取文件的内容。
  • FileReader.readAsText()
    开始读取指定的Blob中的内容。一旦完成,result属性中将包含一个字符串以表示所读取的文件内容。

从Blob中读取内容的唯一方法是使用 FileReader。以下代码将 Blob 的内容作为url读取:

var oImg = new Image();
var reader = new FileReader();
reader.readAsDataURL(files[0]);
reader.onload = function (e) {
              base64Code = this.result;
              oImg.src = base64Code;
              oPic.style = "background:"+ 'url(\''+base64Code+'\') no-repeat'+ ';background-position:center;background-size:auto 100%;background-color: white;'
            }

在上述代码中,我们把上传图片绑定到input的change事件上,通过FileReader对象来异步读取存储在用户计算机上的文件

onload事件会在文件读取成功之后触发,FileReader对象的result属性存储着data: URL格式的字符串,我们把读取到的图片url赋值给input外包着的div结点以及新创建的img对象,给用户做出图片已经上传的假象

使用canvas压缩图片

我们首先了解一下canvas

  • canvas 元素不被一些老的浏览器所支持,但是所有的主流浏览器的新近版本都支持。Canvas 的默认大小为300像素×150像素(宽×高,像素的单位是px)。但是,可以使用HTML的高度和宽度属性来自定义Canvas 的尺寸。
  • canvas起初是空白的。为了展示,首先脚本需要找到渲染上下文,然后在它的上面绘制。它元素有一个叫做 getContext() 的方法,这个方法是用来获得渲染上下文和它的绘画功能。getContext()只有一个参数,即上下文的格式。

在获得了源图对象的情况下,可以使用 drawImage 方法将它渲染到 canvas 里。

  • drawImage(image, x, y)
    其中 image 是 image 或者 canvas 对象,x 和 y 是其在目标 canvas 里的起始坐标。
  • drawImage(image, x, y, width, height)
    这个方法多了2个参数:width 和 height,这两个参数用来控制缩放的图片大小
  • drawImage(image, sx, sy, sWidth, sHeight, dx, dy, dWidth, dHeight)
    第一个参数和其它的是相同的,都是一个图像或者另一个 canvas 的引用。前4个是定义图像源的切片位置和大小,后4个则是定义切片的目标显示位置和大小。
    canvas.toBlob(callback, mimeType, qualityArgument) 创造Blob对象,用以展示canvas上的图片;这个图片文件可以被缓存或保存到本地,由用户代理端自行决定。

callback
回调函数,可获得一个单独的Blob对象参数。
type 可选
DOMString类型,指定图片格式,默认格式为image/png。
encoderOptions 可选
Number类型,值在0与1之间,当请求图片格式为image/jpeg或者image/webp时用来指定图片展示质量。如果这个参数的值不在指定类型与范围之内,则使用默认值,其余参数将被忽略。

接着上面来,之前我们已经获得了图片的base64,所以我们可以新生成一个Image对象,在监听该Image的load事件时,利用的canvas可以再获取源图对象的情况下,使用drawImage(image,x,y,width,height)的方法对图片进行压缩,然后利用canvas.toBlob将画好的canvas转为blob文件。

oImg.onload = function() {
            var canvas = document.createElement('canvas');
            var context = canvas.getContext('2d');

			//获取图片的原始宽高
            var originW = oImg.width;
            var originH = oImg.height;

			//设置图片压缩后的最大宽高
            var maxW = 120, maxH = 120;
            var targW = originW, targH = originH;
            if(originW > maxW || originH > maxH) {
              if(originH/originW > maxH/maxW) {
                targH = maxH;
                targW = Math.round(maxH * (originW / originH));
              }else {
                targW = maxW;
                targH = Math.round(maxW * (originH / originW));
              }
            }
            //对图片进行缩放canvas.toblob
            canvas.width = targW;
            canvas.height = targH;
            //清除画布,在画之前清是因为会存在多次绘制的情况
            context.clearRect(0,0,targW,targH);
            //图片压缩
            context.drawImage(oImg,0,0,targW,targH);

利用formdate上传文件

我们可以自己创建一个FormDate对象,然后调用它的append方法来添加字段吗,像这样

var formData = new FormData();
formData.append("userfile", fileInputElement.files[0]);

使用append()方法时,可以通过第三个可选参数设置发送请求的头 Content-Disposition 指定文件名。如果不指定文件名(或者不支持该参数时),将使用名字“blob”。

  • 一个 Blob对象表示一个不可变的, 原始数据的类似文件对象。Blob表示的数据不一定是一个JavaScript原生格式。 File 接口基于Blob,继承 blob功能并将其扩展为支持用户系统上的文件。你可以通过 Blob() 构造函数创建一个Blob对象。
            var newUrl = canvas.toDataURL('image/jpeg', 0.5);
            //canvas转为blob并上传
            canvas.toBlob(function (blob) {
              var formData = new FormData();
              formData.append("file",blob);
              _this.$axios.post('weekly_war/user/photo.do', formData, {emulateJSON : true, withCredentials : true}).then(function(res) {
                  if(res.data.success) {
                   showPopRight(res.data.msg,_this);
                   window.localStorage.setItem('pic',base64Code);
                  }else {
                    showPopError(res.data.msg,_this);
                  }
              })
            },files.type || 'image/png');
          }

FormData 对象的字段类型可以是 Blob, File, 或者 string: 如果它的字段类型不是Blob也不是File,则会被转换成字符串类。
注意,axios的配置里不要设置
{
headers: {
‘Content-Type’: ‘multipart/form-data’
}
}
正常以 multipart/form-data 编码方式提交请求体,生成的content-type 应该是这样的
Content-Type: multipart/form-data; boundary=----WebKitFormBoundary5NqxviCXpyAjOEV6
boundary 是浏览器自动生成的分割符, 如果自己设置了Content-Type,boundary 就会被覆盖掉,导致发送的FormData数据,参数为空

在这里插入图片描述

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值