郑重正告:本文止于技术钻研,请勿在本人的生产环境应用别人图片资源。
通常在开发测试环节,一些资源图片会呈现防盗链的谬误提醒,本文就通过前端根底技术,实现根本的图片跨站显示成果。
防盗链的原理:
- 服务端通过申请头的
request.headers.referer
来判断是否是本人资源白名单的申请起源。 - 如果 referer=null, 则无奈判断起源,会失常显示图片。
所以基于以上实践,能够给图片发明一个没有 referer 的申请环境就能够实现了。
解决思路:
通过 iframe 来实现无 referer 的申请环境。
实现过程:
- 创立一个 base64 长期资源,供 iframe 调用
- 在长期资源中,申请图片
- 图片加载实现后,批改 iframe.height=img.height
源码
base64 长期资源:
const src = 'http://test.com/test.png';
const html = `data:text/html;base64,${btoa(`<img src="${src}"/>`)}`
<iframe src="html"></iframe>
应用 ResizeObserver 监听图片高度
因为以后 iframe 里只有一个图片,所以监听 body 高度即可(body 有默认 margin,前面须要革除款式)。(ResizeObserver API)
var ro = new ResizeObserver(entries => {for (let entry of entries) {const data = {height: entry.contentRect.height};
window.parent?.postMessage({...data, window: 'parent'}, '*')
window.top?.postMessage({...data, window: 'top'}, '*')
}
})
ro.observe(document.body)
window.addEventListener("message", e => {if (e.data.window === 'parent') {iframe.style.height = e.data.height + 'px'}
}, false)
残缺代码 (vue3 setup ts)
<script setup lang="ts">
import {onMounted, ref, withDefaults} from 'vue'
interface IProps {
src: string;
id?: string
}
const props = withDefaults(defineProps<IProps>(), {});
const iframe = ref(null)
onMounted(() => {if (iframe.value) {const html = `<style>body{margin:0;}</style>
<img src="${props.src}" style="display:block"/>
<script>
var ro = new ResizeObserver(entries => {for (let entry of entries) {const data = {height: entry.contentRect.height, id: "${props.id || props.src}"};
window.parent?.postMessage({...data, window: 'parent'}, '*')
window.top?.postMessage({...data, window: 'top'}, '*')
}
})
ro.observe(document.body)
<\/script>`
iframe.value.src = `data:text/html;base64,${btoa(html)}`
}
window.addEventListener("message", e => {if (e.data.window === 'parent' && e.data.id === props.src && iframe.value) {iframe.value.style.height = e.data.height + 'px'}
}, false)
})
</script>
<template>
<iframe ref="iframe" style="display: block; border: 0;"></iframe>
</template>
此文为自己原创翻新文章,转发请注明起源。