郑重正告:本文止于技术钻研,请勿在本人的生产环境应用别人图片资源。

通常在开发测试环节,一些资源图片会呈现防盗链的谬误提醒,本文就通过前端根底技术,实现根本的图片跨站显示成果。

防盗链的原理:

  1. 服务端通过申请头的request.headers.referer来判断是否是本人资源白名单的申请起源。
  2. 如果referer=null,则无奈判断起源,会失常显示图片。

所以基于以上实践,能够给图片发明一个没有referer的申请环境就能够实现了。

解决思路:

通过iframe来实现无referer的申请环境。

实现过程:

  1. 创立一个base64长期资源,供iframe调用
  2. 在长期资源中,申请图片
  3. 图片加载实现后,批改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>

此文为自己原创翻新文章,转发请注明起源。