赞
踩
文件图片上传,客户端预览是很正常的需求,获取文件的md5特征码也是很正常的,那么,在uniapp中三种环境,h5, 小程序以及 app环境下,如何实现的?
参考:
如何在uniapp中读取文件ArrayBuffer和sha256哈希值,支持H5、APP、小程序
uniapp 没有提供跨平台的 API 来获取文件的 sha256 哈希值和读取文件的 ArrayBuffer,因此需要开发者自己手动兼容各个平台。在小程序端使用FileSystemManager、app 端是plus.io、H5 端是FileReader,这些 API 都是平台特有的,而且实际调用存在各种问题,也缺乏相关教程
ps:只适合小文件上传,大文件的话不要用这个。计算md5的时候采用了sparkMD5,请自行安装。
必须要知道的是文件的临时路径,就是:
http://xxxxx 形式的
例如:
// 读取图像文件
uni.chooseImage({
count: 9,
sizeType: ['original', 'compressed'],
sourceType: ['album', 'camera'],
success: (res) => {
const tempFilePaths = res.tempFilePaths
// tempFilePaths 是一个数组,可以通过索引获取图片路径,比如tempFilePaths[0],我们需要的就是这个路径
},
})
或者
uni.chooseMedia({
count:1,// 限制选取图像数量
mediaType:["image"],// 设置选取资源为图片类型
sourceType:["album","camera"],// 设置图像来源:相册或相机
camera:"back",// 设置相机为后置摄像头
success:(res)=>{
// 获取微信拿到的图片的临时地址并保存到本地
this.photoPath=res.tempFiles[0].tempFilePath;
}
})
},
arrayBuffer:
// 小程序,filePath 是一个本地文件路径
const fs = uni.getFileSystemManager()
return fs.readFileSync(filePath)
base64:
// (由于uniapp开发所以uni打头)
uni.getFileSystemManager().readFile({// 【重点来啦】人家自提供的转码API
filePath:image.path,// 所需转码图像路径
encoding:"base64",// 转码类型
success:(res)=>{
// 生成base64
let imageBase64='data:image/'+image.type+';base64,'+res.data;
console.log('转base64后:',imageBase64);
}
})
const blobURLToBlob = (url) => { return new Promise((resolve, reject) => { var http = new XMLHttpRequest() http.open('GET', url, true) http.responseType = 'blob' http.onload = function (e) { if (this.status == 200 || this.status === 0) { resolve(this.response) } else { reject(this.status) } } http.send() }) } // 通过blob:url读取实际的ArrayBuffer数据 const H5ReadBlobUrlArrayBuffer = (blobUrl) => { return new Promise(async (resolve, reject) => { try { const reader = new FileReader() // blob数据转file对象数据 const fileBlob: any = await blobURLToBlob(blobUrl) const file = new window.File([fileBlob], 'file.name', { type: 'file.type' }) // 读取file对象ArrayBuffer reader.readAsArrayBuffer(file) reader.onload = function (e) { resolve(e?.target?.result) } } catch (e) { reject(e) } }) } // 通过blob:url读取实际的base64: const H5ReadBlobUrlBase64 = (blobUrl) => { return new Promise(async (resolve, reject) => { try { const reader = new FileReader() // blob数据转file对象数据 const fileBlob: any = await blobURLToBlob(blobUrl) const file = new window.File([fileBlob], 'file.name', { type: 'file.type' }) // 读取file对象ArrayBuffer reader.readAsDataURL(file) reader.onload = function (e) { resolve(e?.target?.result) } } catch (e) { reject(e) } }) } 注意:实际上 h5都是使用fileReader的api来读取的,arrayBuffer是:readAsArrayBuffer,而base64是readAsDataURL,不但图片,文件也能这样读取base64的。
const H5PlusReadFileArrayBuffer = (filePath) => { return new Promise((resolve, reject) => { try { plus.io.resolveLocalFileSystemURL( filePath, function (entry) { entry?.file(function (file) { const fileReader = new plus.io.FileReader() fileReader.readAsDataURL(file, 'utf-8') fileReader.onloadend = function (evt) { const result = { base64: evt.target.result.split(',')[1], size: file.size, } resolve(uni.base64ToArrayBuffer(result.base64)) } }) }, function (error) { reject(error) }, ) } catch (error) { reject(error) } }) }
app方面是直接先读取base64,再读取arrayBuffer,所以一气呵成。
import SparkMD5 from 'spark-md5'; export interface FileReaderInfo { fileHeader64:string;//--base64形式的文件前一段内容,用于传递magicNumber进行判断。 base64:string; arrayBuffer:any; tempPath:string;//形式如下:blob:http://localhost:3000/5fd140d3-1372-4394-8b08-0cba8c508099 mime:string; errMsg?:string; md5:string,//--获取文件md5. } // #ifdef H5 // 通过blob:url读取实际的blob数据 function h5_blobURLToBlob (url:string) :Promise<any> { return new Promise((resolve, reject) => { var http = new XMLHttpRequest(); http.open('GET', url, true) http.responseType = 'blob'; http.onload = function (e) { if (this.status == 200 || this.status === 0) { resolve(this.response) } else { reject(this.status) } }; http.send() }) } // 通过blob:url读取实际的ArrayBuffer数据 function H5ReadBlobUrl(blobUrl:string,mimeType:string): Promise<FileReaderInfo> { let intervalInst:any=null; const fileinfo:FileReaderInfo={ fileHeader64:"", tempPath:blobUrl, arrayBuffer:null, base64:"", mime:mimeType, md5:"", }; return new Promise<FileReaderInfo>(async (resolve, reject) => { try { const reader = new FileReader(); const reader64 = new FileReader(); // blob数据转file对象数据 const fileBlob: any = await h5_blobURLToBlob(blobUrl); const file = new window.File([fileBlob], 'file.name', { type: mimeType }); // 读取file对象ArrayBuffer reader.readAsArrayBuffer(file); reader64.readAsDataURL(file); reader.onload = function (e) { const data:any=e?.target?.result; // let spark = new SparkMD5(); // 创建md5对象(基于SparkMD5) let spark = new SparkMD5.ArrayBuffer(); spark.append(data); fileinfo.md5=spark.end(); fileinfo.arrayBuffer=data; }; reader64.onload = function (e) { fileinfo.base64=(e?.target?.result+""); let subPosIdx = (fileinfo.base64 + "").indexOf(","); let headerContent = fileinfo.base64.substr(subPosIdx + 1, 160); fileinfo.fileHeader64=headerContent; }; intervalInst=setInterval(()=>{ if(fileinfo.base64&&fileinfo.arrayBuffer){ clearInterval(intervalInst); resolve(fileinfo); } },100); } catch (e) { if(intervalInst){ clearInterval(intervalInst); } reject(e) } }) } // #endif // #ifdef APP-PLUS // 通过plus.io读取文件的ArrayBuffer数据 function H5PlusReadFile (filePath:string,mimeType:string) :Promise<FileReaderInfo> { const fileinfo:FileReaderInfo={ fileHeader64:"", tempPath:filePath, arrayBuffer:null, base64:"", mime:mimeType, md5:"", }; return new Promise<FileReaderInfo>((resolve, reject) => { try { plus.io.resolveLocalFileSystemURL( filePath, function (entry:any) { entry?.file(function (file:any) { const fileReader = new plus.io.FileReader(); fileReader.readAsDataURL(file, 'utf-8'); fileReader.onloadend = function (evt:any) { fileinfo.base64=(evt?.target?.result+""); let subPosIdx = (fileinfo.base64 + "").indexOf(","); let headerContent = fileinfo.base64.substr(subPosIdx + 1, 160); fileinfo.fileHeader64=headerContent; const result = { base64: evt.target.result.split(',')[1], size: file.size, }; const data:any=uni.base64ToArrayBuffer(result.base64); // let spark = new SparkMD5(); // 创建md5对象(基于SparkMD5) let spark = new SparkMD5.ArrayBuffer(); spark.append(data); fileinfo.md5=spark.end(); fileinfo.arrayBuffer=data; resolve(fileinfo); } }) }, function (error) { reject(error) }, ) } catch (error) { reject(error) } }) } // #endif function MpReadFile(filePath:string,mimeType:string) :Promise<FileReaderInfo>{ const fileinfo:FileReaderInfo={ fileHeader64:"", tempPath:filePath, arrayBuffer:null, base64:"", mime:mimeType, md5:"", }; return new Promise<FileReaderInfo>((resolve, reject) => { if (uni.canIUse('getFileSystemManager') && uni.getFileSystemManager) { }else{ fileinfo.errMsg="无效环境,不可调用api!"; reject(fileinfo); return ; } const fs = uni.getFileSystemManager(); const data:any = fs.readFileSync(filePath); // let spark = new SparkMD5(); // 创建md5对象(基于SparkMD5) let spark = new SparkMD5.ArrayBuffer(); spark.append(data); fileinfo.md5=spark.end(); fileinfo.arrayBuffer=data; fs.readFile({// 【重点来啦】人家自提供的转码API filePath: filePath,// 所需转码图像路径 encoding: "base64",// 转码类型 success: (res) => { // 生成base64 // let imageBase64 = 'data:image/' + image.type + ';base64,' + res.data; let imageBase64 = res.data; console.log('转base64后:', imageBase64); fileinfo.base64=(imageBase64+""); let subPosIdx = (fileinfo.base64 + "").indexOf(","); let headerContent = fileinfo.base64.substr(subPosIdx + 1, 160); fileinfo.fileHeader64=headerContent; resolve(fileinfo); } }); }); } // 对外暴露的方法,通过这个方法获取文件的ArrayBuffer,内部会根据平台调用不同的方法 export const readFileDataExt = async (filePath:string,mimeType:string) : Promise<FileReaderInfo> => { if (uni.canIUse('getFileSystemManager') && uni.getFileSystemManager) { return MpReadFile(filePath,mimeType); } // #ifdef APP-PLUS else if (plus.io) { return H5PlusReadFile(filePath,mimeType); } // #endif // #ifdef H5 else if (XMLHttpRequest) { return H5ReadBlobUrl(filePath,mimeType); } // #endif else { throw new Error('不支持的平台'); } };
选择图片进行上传:图片的数据如下:
ps:文件的md5,不同的文件是一定不同的,如果你获得的md5是一样的—那么就好好检查一下,spark获取md5的时候是不是都是同一个东西了。
Copyright © 2003-2013 www.wpsshop.cn 版权所有,并保留所有权利。