写点什么

前端项目上传图片,压缩,拍照图片旋转解决方案

用户头像
关注
发布于: 2021 年 05 月 10 日
1.使用 input 标签上传
capture = 'user' 调用前置摄像头, 'environment' 调用后置摄像头<input type="file" multiple id="imgFile" accept="image/*" capture=""/>
复制代码
2.获取上传的数据

$refs!: { imgFile: any;};
const file = e.target.files[0];const rFilter = /\.(png|jpg|gif|jpeg|webp)$/; // 检查图片格式
if (!rFilter.test(file.type)) { alert('请上传图片'); this.$refs.imgFile.value = ''; return false}
复制代码
3.使用 FileReader 对象读取文件类型
  1. 主要使用如下方法FileReader.onload,FileReader.readAsArrayBuffer(),FileReader.readAsDataURL()

/** * 获取文件数据 */enum Type {    readAsArrayBuffer = 'readAsArrayBuffer',    readAsDataURL = 'readAsDataURL',}const getFileData = (file: Blob | object, type?: string): Promise<string | Blob> => {    return new Promise((resolve, reject) => {        const fileReader: any = new FileReader();        switch (type) {            case Type.readAsArrayBuffer:                fileReader.readAsArrayBuffer(file);                break;            case Type.readAsDataURL:                fileReader.readAsDataURL(file);                break;            default:                fileReader.readAsArrayBuffer(file);                break;        }
return fileReader.addEventListener('load', () => { return resolve(fileReader.result); }); });};
复制代码
4.使用 FormData 对象上传文件
const formDate = new FormData()formDate.append(name, value, filename)
复制代码
5.上传文件
 // 设置上传内容格式 headers: {    'Content-Type': 'multipart/form-data'  }// axios 使用onUploadProgress监听上传进度
复制代码
6.移动端拍照旋转的问题(几年没更新,用苹果 7 测试没发现任何问题,返回 6 图片显示也是正常的,上传到服务器也是正常的,本地 node 测试)
  1. 下载 npm i exif-js -S

// 返回方向EXIF.getData(file, function() {  EXIF.getAllTags(this)  return EXIF.getTag(this, 'Orientation')})
复制代码

2.使用本地代码解决

const getOrientation = (buffer) => {    const view = new DataView(buffer);    if (view.getUint16(0, false) !== 0xFFD8) { return -2; }    const length = view.byteLength;    let offset = 2;    while (offset < length) {        const marker = view.getUint16(offset, false);        offset += 2;        if (marker === 0xFFE1) {            if (view.getUint32(offset += 2, false) !== 0x45786966) { return -1; }            const little = view.getUint16(offset += 6, false) === 0x4949;            offset += view.getUint32(offset + 4, little);            const tags = view.getUint16(offset, little);            offset += 2;            for (let i = 0; i < tags; i++) {                if (view.getUint16(offset + i * 12, little) === 0x0112) {                    return view.getUint16(offset + i * 12 + 8, little);                }            }            // tslint:disable-next-line: no-bitwise        } else if ((marker & 0xFF00) !== 0xFF00) { break; } else { offset += view.getUint16(offset, false); }    }    return -1;};
// 转换成Bufferconst dataURItoBuffer = (dataURI) => { const byteString = atob(dataURI.split(',')[1]); const buffer = new ArrayBuffer(byteString.length); const view = new Uint8Array(buffer); for (let i = 0; i < byteString.length; i++) { view[i] = byteString.charCodeAt(i); } return buffer;};
复制代码
7.初始化画布大小
  initCanvas(Mw: number, Mh: number, img: any) {    const canvas = document.createElement("canvas");    const ctx = canvas.getContext("2d");    document.body.append(canvas);    // 配置画布最大大小    const maxW: number = Mw;    const maxH: number = Mh;    let w: number = img.width;    let h: number = img.height;
if (w < h && h > maxH) { w = parseInt((maxH * img.width) / img.height); h = maxH; } else if (w >= h && w > maxW) { h = parseInt((maxW * img.height) / img.width); w = maxW; }
canvas.width = w; canvas.height = h; console.log(canvas, w, h, img.width, img.height); }
复制代码


8.使用 canvas 处理方向
// http://stackoverflow.com/questions/19463126/how-to-draw-photo-with-correct-orientation-in-canvas-after-capture-photo-by-usinfunction orientationHelper(canvas, ctx, orientation) {  const w = canvas.width,        h = canvas.height;  if (orientation > 4) {    canvas.width = h;    canvas.height = w;  }  switch (orientation) {    case 3:      ctx.translate(w, h);      ctx.rotate(Math.PI);      break;    case 6:      ctx.rotate(0.5 * Math.PI);      ctx.translate(0, -h);      break;    case 8:      ctx.rotate(-0.5 * Math.PI);      ctx.translate(-w, 0);      break;  }}
复制代码
9.导出画布
// canvas的toDataURL是只能压缩jpg,png图片的透明性质在canvas中是无效的,(win10有透明元素,苹果7,默认就没有)ctx.drawImage(img, 0, 0, w, h);const dataURL = canvas.toDataURL('image/jpeg', quality);
复制代码
10.图片压缩处理完成后转为 blob 格式
const convertBase64UrlToBlob = (a) => {    const arr = a.split(',');    const mime = arr[0].match(/:(.*?);/)[1];    const bstr = atob(arr[1]);    let n = bstr.length;    const u8arr = new Uint8Array(n);    while (n--) {        u8arr[n] = bstr.charCodeAt(n);    }    return new Blob([u8arr], { type: mime });};
复制代码
11.配置 axios,上传文件防止序列化
    transformRequest: [function (data, headers) {        if (headers['Content-Type'] === 'multipart/form-data;charset=UTF-8') {            return data;        }        // 对 data 进行任意转换处理        return Qs.stringify(data);    }],
复制代码
12.触发事件
  async changeFile(e: any) {    const file = e.target.files[0];    const rFilter = /(png|jpg|gif|jpeg|webp)$/; // 检查图片格式
if (!rFilter.test(file.type)) { alert('请上传图片'); this.$refs.imgFile.value = ''; } else { const url = await getFileData(file); this.imgSrc = url; const Orientation = getOrientation(dataURItoBuffer(url)); console.log(Orientation, '方向00');
const img = new Image(); img.src = url; img.onload = () => { this.initCanvas(1000, 1000, img, Orientation); }; } }
复制代码


发布于: 2021 年 05 月 10 日阅读数: 20
用户头像

关注

还未添加个人签名 2020.08.05 加入

还未添加个人简介

评论

发布
暂无评论
前端项目上传图片,压缩,拍照图片旋转解决方案