js+php实现图片弹出下载兼容URL图片

在开发的时候尤其是做前后端分离的时候有时要用到页面弹出个图片然后可以直接保存的功能,这里看下实现逻辑

流程

1、前端拿到图片URL;

2、将URL传给后端由后端直接输出,达到不跨域的目的;

3、前端拿到图片数据,再弹出下载框。

前端JS插件部分


var tools = {
	//图片操作
	image : {
		//将url图片转成base64格式
		url2base64Content(url){
			return new Promise((resolve)=>{
				//jquery版本2似乎不行,用3成功了
				$.ajax({
					url : '/tool.php',
					type : 'POST',
					data : {
					    act : 'remoteImage',
					    remoteUrl : url
					},
					xhrFields: {
						withCredentials : true, //可用于获取响应头
						responseType : 'blob', //响应格式
					},
					success : function(data,status,xhr){
						let contenttype = xhr.getResponseHeader('Content-Type'); //eg: image/png
						var freader = new FileReader();
						freader.readAsDataURL(data);
						freader.onload = function(e){
							return resolve({
								data : e.target.result,
								contentType : contenttype
							});
						}
					},
					error : function(){
						return resolve(null)
					}
				})
			})
		},
		
		//contentType转文件后缀
		getExtentionWithContentType(contentType,defaultExt){
			contentType = contentType.toLowerCase();
			defaultExt = defaultExt || 'jpg';
			let arr = {
				jpeg : 'jpg',
				png : 'png',
				gif : 'gif',
				bmp : 'bmp',
				icon : 'ico'
			}
			for(let mine in arr){
				if(contentType.indexOf(mine) != -1){
					return arr[mine];
				}
			}
			return defaultExt;
		},
		
		//下载图片,推荐让当前页面也是https
		downloadImage(base64content,savename){
			var a = document.createElement('a');
			a.href = base64content;
			a.download = savename;
			a.click();
		}
	}
}	



后端PHP部分,得到图片数据并输出到浏览器,不限本地和远程,所以可以实现跨域,如果是不跨域可以不用这一步


$remoteUrl = 'http://xxx.jpg';
if(substr($remoteUrl,0,4) != 'http'){
	//本地图片,转成URL形式或本地绝对路径或本地相对路径
	$remoteUrl = ltrim($remoteUrl,'/');
	$remoteUrl = APP_URL . '/' . $remoteUrl;
}
$ext = explode('.',$remoteUrl);
$ext = end($ext);
if($ext == 'jpg'){
	$ext = 'jpeg';
}

header('Content-Type: image/' . $ext);
$fp = @fopen($remoteUrl, "rb"); //二进制方式打开文件
if($fp !== false){
	fpassthru($fp); // 输出至浏览器
	fclose($fp);
}


前端调用示例代码


/////---------------调用示例
async function showImageDownload(img_url){
	let base64content = await tools.image.url2base64Content(img_url);
	if(base64content){
		let ext = tools.image.getExtentionWithContentType(base64content.contentType);
		tools.image.downloadImage(base64content.data,'图片.' + ext)
	}
}

看看前端执行效果