前端---图片上传下载压缩那点事(Blob+File+URL+FileReader)

图片上传下载与压缩

Blob

创建 Blob 实例对象

Blob 对象的属性

Blob实例

File

URL

URL.createObjectURL(blob:Blob)

URL.revokeObjectURL(objectURL)

FileReader

创建FileReader实例对象

常用属性

常用事件

常用方法

图片上传

图片直接上传

图片压缩后上传


图片上传下载与压缩

Blob

        Blob (Binary Large Object) 对象代表了一段二进制数据,提供了一系列操作接口。其他操作二进制数据的API(如 File 对象),都是建立在 Blob 对象基础上的,继承了它的属性和方法。

创建 Blob 实例对象

        Blob 构造函数,接受两个参数。第一个参数是一个包含实际数据的数组,这个数组中的元素可以为 DOMString ,或者 ArrayBuffer,第二个参数是数据的类型,这两个参数都不是必需的。

var blob = new Blob(["Hello World"], {type: 'text/html'});

Blob 对象的属性

  • size属性
var blob = new Blob(["Hello World"], {type: 'text/html'});
console.log(blob.size) // 11
  • type属性
var blob = new Blob(["Hello World"], {type: 'text/html'});
console.log(blob.type) // text/html

Blob实例

// 创建Blob实例对象,通过超链接下载文件
var blob = new Blob(["Hello World"], {type: 'text/html'});
var elink = document.createElement("a");
elink.href = window.URL.createObjectURL(blob);
elink.download = "hello-world.txt";
elink.textContent = "Download File!";
document.body.appendChild(elink);

File

        JavaScript中,File继承自Blob。即 File extends Blob; 最常使用场景是通过 <input type="file"> 上传文件时。File实例对象有三个常用的属性:name(文件名)     size(文件大小,单位为字节)      type(文件的 MIME 类型)

<html>

<body>
    <input type="file" id="fileInput" name="file" multiple="multiple" />
</body>

</html>

<script>
    var fileList = [] // 文件数组集合
    var fileInput = document.getElementById("fileInput")
    fileInput.addEventListener("change", function (event) {
        var file = fileInput.files[0] // 获取文件信息 File实例对象
        fileList.push(file)
        console.log(file)
    })
</script>

URL

       最常用的场景是将二进制文件转为一个 URL ,这个 URL 可以放置于任何通常可以放置 URL 的地方,比如 img 标签的 src 属性。

URL.createObjectURL(blob:Blob)

<html>

<body>
    <input type="file" id="fileInput" name="file" multiple="multiple" />
</body>

</html>

<script>
    var fileList = []; // 文件数组集合
    var fileInput = document.getElementById("fileInput")
    fileInput.addEventListener("change", function (event) {
        var file = fileInput.files[0] // File
        fileList.push(file)


        // URL.createObjectURL(Blob: blob) 二进制数据转url
        var imgUrl = URL.createObjectURL(file) // file是File实例,File继承自Blob,因此file也是Blob的一个实例
        var img = new Image() // 创建Image实例对象
        img.src = imgUrl
        img.onload = () => {
            document.body.appendChild(img)
        }
    });
</script>

URL.revokeObjectURL(objectURL)

       移除转化的url,即释放url。

<html>

<body>
    <input type="file" id="fileInput" name="file" multiple="multiple" />
</body>

</html>

<script>
    var fileList = []; // 文件数组集合
    var fileInput = document.getElementById("fileInput")
    fileInput.addEventListener("change", function (event) {
        var file = fileInput.files[0] // File
        fileList.push(file)


        // 下载图片
        var elink = document.createElement('a')
        var downloadUrl = URL.createObjectURL(file)
        elink.href = downloadUrl
        elink.download = file.name // 设置文件的文件名
        elink.textContent = ''
        document.body.appendChild(elink)
        elink.click()
        URL.revokeObjectURL(downloadUrl) // 移除 url
        document.body.removeChild(elink)
    })
</script>

FileReader

    Blob 对象和File对象只是存放二进制数据的容器,本身并不能操作二进制。FileReader 对象就是专门操作二进制数据的。

创建FileReader实例对象

var fileReader = new FileReader()

常用属性

  • result:文件的内容。该属性仅在读取操作完成后才有效。

常用事件

  • onload:处理 load 事件。该事件在读取操作完成时触发。

常用方法

  • readAsDataURL():开始读取指定的 Blob 中的内容。一旦完成,result 属性中将包含一个  data:URL  格式的字符串以表示所读取文件的内容;此时result 属性可以充当url,效果类似于URL.createObjectURL(Blob: blob)生成的url,当两种url是不一样的。
<html>

<body>
    <input type="file" id="fileInput" name="file" multiple="multiple" />
</body>

</html>

<script>
    var fileList = []; // 文件数组集合
    var fileInput = document.getElementById("fileInput")
    fileInput.addEventListener("change", function (event) {
        var file = fileInput.files[0] // File
        fileList.push(file)

        // FileReader 
        var fileReader = new FileReader()
        fileReader.readAsDataURL(file)  // 读文件,读取完后,文件内容会以 data: URL 形式放到 result 属性中
        fileReader.onload = () => {     // onload : 文件读取完后
            // 显示图片
            var img = new Image() // Image对象
            img.src = fileReader.result // 设置图片src为fileReader的result属性
            img.onload = () => {
                document.body.appendChild(img)
            }
        }
    })
</script>

图片上传

图片直接上传

          拿到File实例对象,直接上传。

<template>
  <div class="about">
    <input
      type="file"
      id="fileInput"
      name="file"
      multiple="multiple"
      @change="uploadImg"
    />
  </div>
</template>
<script>
import { defineComponent, getCurrentInstance } from "vue";
export default defineComponent({
  name: "About",
  setup() {
    const { proxy } = getCurrentInstance();
    function uploadImg() {
      var fileInput = document.getElementById("fileInput");
      var file = fileInput.files[0];
      var formData = new FormData();
      formData.append("imgFile", file);
      proxy.$axios
        .post("/avatar/upload", formData) // 网络请求
        .then((result) => {
          console.log(result);
        })
        .catch(() => {
          /* */
        })
    }


    return {
      uploadImg
    }
  }
});
</script>

图片压缩后上传

          图片压缩后,可以再转为File实例对象,然后调接口上传。

<template>
  <div class="about">
    <input
      type="file"
      id="fileInput"
      name="file"
      multiple="multiple"
      @change="uploadImg"
    />
  </div>
</template>
<script>
import { defineComponent, getCurrentInstance } from "vue";
export default defineComponent({
  name: "About",
  setup() {
    const { proxy } = getCurrentInstance();
    function uploadImg() {
      var fileInput = document.getElementById("fileInput");
      var file = fileInput.files[0];
	  var blob = dataURLtoBlob(tobase64(file)); // 压缩图片
      var aasfile = blobToFile(blob, file["name"]); // base64 转 Blob
      var imgFile = new File([aasfile], file["name"], { // Blob 转File
        type: "image/jpeg",
      });
	  var formData = new FormData();
      formData.append("imgFile", imgFile); 
      proxy.$axios.post("/avatar/upload", formData) // 网络请求
        .then((result) => {
             console.log(result);
        }).catch(() => {
             console.log("error");
        });
    }


   /* 
    *  参数blob : Blob(File)实例对象,即二进制数据对象
    *  图片压缩思路:
    *       1.通过FileReader将Blob实例对象(二进制数据对象)转为一个url,赋给Image实例对象的src属性;
    *       2.再通过Canvas的drawImage方法画图,最后再通过Canvas的toDataURL()方法进行Base64压缩,返回DataURL
    */
    function tobase64(blob) {
        var fileReader = new FileReader()
        fileReader.readAsDataURL(blob)
        fileReader.onload = () => {     // onload : 文件读取完后事件
            var img = new Image()
            img.src = fileReader.result
            img.onload = () => {
                const canvas = document.createElement('canvas')
                const ctx = canvas.getContext('2d') // 平面图画笔
                const width = img.width
                const height = img.height 
                canvas.width = width    // 画布宽 = 图片宽
                canvas.height = height  // 画布高 = 图片高
                ctx.drawImage(img, 0, 0, width, height)
                const dataURL = canvas.toDataURL('image/jpeg', 0.6) // 第二个参数:值越小,压缩后的图片越模糊
                // console.log(dataURL)
                // document.body.appendChild(canvas) // 显示画好的图片
                return dataURL
            }
        }
    }

    //将base64转换为blob  参数dataUrl:压缩后的dataUrl
    function dataURLtoBlob(dataUrl) {
      var arr = dataUrl.split(","),
        mime = arr[0].match(/:(.*?);/)[1],
        bstr = atob(arr[1]),
        n = bstr.length,
        u8arr = new Uint8Array(n);
      while (n--) {
        u8arr[n] = bstr.charCodeAt(n);
      }
      return new Blob([u8arr], { type: mime });
    }

    //将blob转换为file
    function blobToFile(theBlob, fileName) {
      theBlob.lastModifiedDate = new Date();
      theBlob.name = fileName;
      return theBlob;
    }

    return {
      uploadImg,
    };
  },
});
</script>

猜你喜欢

转载自blog.csdn.net/qq_39115469/article/details/113853891