移动端上(传图片太大)处理方案

图片上传思路准备工作都做完了,那怎样用这些材料完成一件事情呢。这里要强调的是,考虑到移动端流量很贵,所以有必要对大图片进行下压缩再上传。图片压缩很简单,将图片用canvas画出来,再使用canvas.toDataUrl方法将图片转成base64格式。所以图片上传思路大致是:监听一个input(type=‘file’)的onchange事件,这样获取到文件file;将file转成dataUrl;然后...
摘要由CSDN通过智能技术生成

利用FileReader和FormData实现图片预览和上传(base64转二进制文件)

监听表单文件变化

文件表单的样式主要通过让它后面,通过别的DOM来美化它。

<input type="file">
input.on.('change', preview);

预览

预览使用 FileReader 对象来读:

function preview(e) {
   
    var file = e.target.files[0];
    var reader = new FileReader();

    reader.onloadend = function () {
   
        // 图片的 base64 格式, 可以直接当成 img 的 src 属性值
        var dataURL = reader.result;
        var img = new Image();
        img.src = dataURL;
        // 插入到 DOM 中预览
        // ...
    };

    reader.readAsDataURL(file); // 读出 base64

}

提交图片文件(二进制文件 非 base64)

base64 转 二进制文件

/**
 * dataURL to blob, ref to https://gist.github.com/fupslot/5015897
 * @param dataURI
 * @returns {Blob}
 */
function dataURItoBlob(dataURI) {
    var byteString = atob(dataURI.split(',')[1]);
    var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];
    var ab = new ArrayBuffer(byteString.length);
    var ia = new Uint8Array(ab);
    for (var i = 0; i < byteString.length; i++) {
        ia[i] = byteString.charCodeAt(i);
    }
    return new Blob([ab], {type: mimeString});
}

构造 FormData 填充二进制文件数据,通过 ajax 的方式进行提交:

var fd = new FormData();
var blob = dataURItoBlob(dataURL);
fd.append('file', blob);


$.ajax({
    type: 'POST',
    url: '/upload',
    data: fd,
    processData: false, // 不会将 data 参数序列化字符串
    contentType: false, // 根据表单 input 提交的数据使用其默认的 contentType
    xhr: function() {
        var xhr = new window.XMLHttpRequest();
        xhr.upload.addEventListener("progress", function(evt) {
            if (evt.lengthComputable) {
                var percentComplete = evt.loaded / evt.total;
                console.log('进度', percentComplete);
            }
        }, false);

        return xhr;
    }
}).success(function (res) {
   
    // 拿到提交的结果
}).error(function (err) {
   
    console.error(err);
});

注意:不要漏了指定 processData 和 contentType 为 false 。

压缩

业务中不需要前端不需要压缩,因为后端有更靠谱的压缩方案,但是前端其实也可以压缩,那就是用 canvas 把图画出适合的大小,然后上传。

主要流程:
  • 在 new 出来的 Image 对象,我们监听它的 onload 事件
  • 按照压缩比例,算出压缩后的图片尺寸
  • 创建 canvas ,尺寸设置成上一步骤算出来的压缩后的图片尺寸
  • 调用 drawImage 方法,把图片绘制到 canvas 中
  • 调用 canvas 的 toDataURL ,取出 base64 格式的数据
  • 后续的传图步骤和上面的原图上传一样
var img = new Image();

img.onload = function () {
   
    // 当图片宽度超过 400px 时, 就压缩成 400px, 高度按比例计算
    // 压缩质量可以根据实际情况调整
    var w = Math.min(400, img.width);
    var h = img.height * (w / img.width);
    var canvas = document.createElement('canvas');
    var ctx = canvas.getContext('2d');

    // 设置 canvas 的宽度和高度
    canvas.width = w;
    canvas.height = h;

    // 把图片绘制到 canvas 中
    ctx.drawImage(img, 0, 0, w, h);

    // 取出 base64 格式数据
    var dataURL = canvas.toDataURL('image/png');

    // ...
};

img.src = reader.result;

自己的 OneWord 客户端的上传组件就是这么做的: ow-image-uploader.vue

这样一看,好像除去业务逻辑的话,好像也没多少代码

具体思路:

select local file -> Blob -> DataUrl -> Canvas compress -> DataUrl -> Blob -> Upload file

一、input:file属性

属性值有以下几个比较常用:

accept:表示可以选择的文件MIME类型,多个MIME类型用英文逗号分开,常用的MIME类型见下表。

multiple:是否可以选择多个文件,多个文件时其value值为第一个文件的虚拟路径。

1、accept

只能选择png和gif图片

<input id="fileId1" type="file" accept="image/png,image/gif" name="file" />
  • 0
    点赞
  • 12
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值