@xfl/hx_uniapp_img-downloader
Version:
使用环境为uniapp, 将网络或项目中的图片下载到本地 兼容 h5 小程序 app
163 lines (142 loc) • 4.63 kB
JavaScript
;
/**
* 下载图片的模块
* @version 1.1.0
* @author xfl <541151284@qq.com>
*/
class Downloader{
Downloader = Downloader;
/**
* 开始下载图片
* @public
* @param {String} url 图片的url
* @param {String} [name] 下载后图片的名字
* @returns {Promise} [err, res]
* @example
*
let promise = downloader.load(url, imgName);
promise.then(([err, res])=>{
console.log(err, res); // err 和 res 只会有一个存在,另一个为null
});
*/
async load(url, name){
url = url.trim();
name = this.getName(url, name); //重新计算存储的文件名及扩展名
let err, res;
if( !this.isRemoteUrl(url) ){
// #ifdef APP-PLUS || MP
[err, res] = [null, {tempFilePath: url}];
// #endif
}else{
//在web端时,downloadFile的作用只是 确定当前的资源和网络,可能会拿到一些下载失败的信息
[err, res] = await uni.downloadFile({url: url});
if(err){ //h5下载图片的跨域在这一步就能知道
return [err, null];
}else if(res.statusCode !== 200){ //可能是404
res.errMsg = "downloadFile:fail";
return [res, null];
}
}
// #ifdef H5
try{
//如果这里传入 url,则会在另一个窗口打开图片,而不是下载
this.webDownloadImg(res.tempFilePath, name);
}catch(e){
e.errMsg = e.errMsg || e.message || '';
return [e, null];
}
// #endif
// #ifdef MP-ALIPAY
return [{errMsg: 'plat not support download!'}, null]; //在支付宝小程序中,不支持saveImageToPhotosAlbum,需要使用其它的方式实现下载
// #endif
// #ifdef APP-PLUS || MP
[err, res] = await uni.saveImageToPhotosAlbum({filePath: res.tempFilePath});
if( err ){
return [err, null];
}
// #endif
return [null, res];
}
/**
* 计算文件名及扩展名
* @public
* @param {String} url 一个url, 当没有传入文件名时,可以尝试从这个url中去获取文件名
* @param {String} [name] 文件名 或 文件名.扩展名
* @param {String} [ext] 扩展名
* @returns {String} 文件名.扩展名
* @example
*
* 1. getName('aaa/bbbb.txt');
* //=> bbbb.txt
*
* 2. getName('aaa/bbbb.txt', 'uuuuu');
* //=> uuuuu.txt
*
* 3. getName('aaa/bbbb.txt', 'uuuuu', '.js');
* //=> uuuuu.js
*
* 4. getName('aaa/bbbb.txt', 'uuuuu.kkk', '.js');
* //=> uuuuu.js
*
* 5. getName('aaa/bbbb.txt', 'uuuuu.kkk');
* //=> uuuuu.kkk
*/
getName(url, name, ext){
let arr = url.match(/(([\w\d_\-]+)(\.[\w\d_]+))$/); //默认取地址中的文件名
//取出 url 中的文件名和扩展名
let defaultName = '__default', defaultExt = '.png';
if(arr){
defaultName = arr[1] || defaultName;
defaultExt = arr[3] || defaultExt;
}
//取出传入的 name 中的文件名和扩展名
arr = name.match(/\.[\w\d_]+$/);
if(arr){
ext = ext || arr[0];
name = name.replace(/\.[\w\d_]+$/, ''); //去掉name中的扩展名
}
ext = ext || defaultExt;
name = name || defaultName;
return name + ext;
}
/**
* 是否是远程地址
* @public
* @param {String} url 需要判断的url
* @returns {Boolean}
*/
isRemoteUrl(url){
return !!url.match(/^https?:\/\//i);
}
/**
* 在web端通过a标签来下载文件
* 注意,在浏览器中用户可能设置了阻止下载文件,此时代码也会正常执行完成,但其实是没有真正地下载文件的。
* 如果不存在这样的资源,则默认会下载本网页(html文件)
* @public
* @param {String} url 要下载的图片地址
* @param {String} [name=''] 下载后图片的名字
*/
webDownloadImg(url, name = ''){ //网页中的图片下载
const body = document.getElementsByTagName('body')[0];
const aEle = document.createElement('a');
aEle.setAttribute('download', name);
aEle.style.display = 'none';
aEle.href = url;
aEle.target = '_blank';
body.appendChild(aEle);
aEle.dispatchEvent( new MouseEvent('click') ); // 模拟鼠标click点击事件
document.body.removeChild(aEle);
}
/**
* 以单例模式 获取实例对象
* @static
* @public
*/
static getInstance(){
if(!this.__hasInstance){
this.__hasInstance = new this();
}
return this.__hasInstance;
}
}
export default Downloader.getInstance();