Skip to content

前端文件操作

以下将介绍自定义对文件进行操作的一些注意点

前端读取使用文件一般需要对 File 进行处理,下列是处理的方式

reader.readAsDataURL(f); // 将 Blob 或 File 读取为 data:URL格式的字符串(base64编码)

reader.readAsBinaryString(f); // 将 Blob 或 File 读取为文件原始二进制格式

reader.readAsArrayBuffer(f); // 将 Blob 或 File 读取为 ArrayBuffer 对象

reader.readAsText(f); // 将 Blob 或 File 读取为内容(字符串形式)

笔者是拖拽获取到的File ,代码如下

js
this.$refs.dragArea.ondrop = (e) => {
	e.dataTransfer.files[0] // 拖拽的一个文件
}

前端使用上传接口一般要传递FormData对象,此时content-type应为multipart/form-data(笔者未进行配置浏览器便自动识别为multipart/form-data),手动配置大致如下

js
// 发票上传
export function apiPostUpload(data) {
  return request({
    url: portalPrefix + '/wallet/upload',
    method: 'post',
    headers:{'Content-Type':'multipart/form-data'}, // 这里设置了
    data
  });
}

值得注意的multipart/form-data这种方法传递的date需要是FormData类

js
const formData = new FormData();
formData.append('userid', this.$store.state.user.userInfo.nsrid);
formData.append('utype', 1);
formData.append('file', this.file);
const res = await apiPostUpload(formData);

前端下载文件

文件流直接window.open(),base64可以用一下方法进行解析(转为blob并创建可下载的url)

js
/**
 * @author sqm
 * @description 将blob转回文件并下载
 * @param {String} base64Url     要下载的base64
 * @backDes 
 */
const downloadBase64 = (base64Url, downloadName = 'download') => {
    //  获取后缀
    let arr = base64Url.split(','), mime = arr[0].match(/:(.*?);/)[1];
    let suffix = arr[0].match(/\/(.*);/)[1];
  
	if('msSaveOrOpenBlob' in navigator){
		//ie使用的下载方式
        base64Url = base64Url.replace(/[\n]/g,""); // 去除换行符
		// 截取base64的数据内容(去掉前面的描述信息,类似这样的一段:data:image/png;base64,)并解码为2进制数据
        var bstr = atob(base64Url.split(',')[1]);
        // 获取解码后的二进制数据的长度,用于后面创建二进制数据容器
        var n = bstr.length;
        // 创建一个Uint8Array类型的数组以存放二进制数据
        var u8arr = new Uint8Array(n);
        // 将二进制数据存入Uint8Array类型的数组中
        while (n--) {
            u8arr[n] = bstr.charCodeAt(n);
        }
        // 创建blob对象
        var blob = new Blob([u8arr]);
        // 调用浏览器的方法,调起IE的下载流程
        window.navigator.msSaveOrOpenBlob(blob, `${downloadName}.${suffix || 'pdf'}`);
	} else{
        // 非ie下载
        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 });
        }
        function downloadFile(url,name='download'){
            var a = document.createElement("a");
            a.setAttribute("href",url);
            a.setAttribute("download",name);
            a.setAttribute("target","_blank");
            let clickEvent = document.createEvent("MouseEvents");
            clickEvent.initEvent("click", true, true);  
            a.dispatchEvent(clickEvent);
        }
      
        function downloadFileByBase64(base64,name){
            var myBlob = dataURLtoBlob(base64);
            var myUrl = URL.createObjectURL(myBlob);
            downloadFile(myUrl,name);
        }

        downloadFileByBase64(base64Url, `${downloadName}.${suffix || 'pdf'}`);
	}
};

export default downloadBase64;

注意:移动端a标签模拟点击下载除了图片都会出现问题,不要考虑用base64来下载。另外前端调用接口下载时可能出现下载文件损坏,主要可能是responseType未设置,或mockjs包导致的,该问题详细可见笔者的《前端下载文件时损坏》这篇博客

鄂ICP备19018246号-1