#1 - 2023-5-20 17:00
=L=+
从 bgm.tv 请求也会cors

在写用户脚本,想要做用户曾用头像功能,要把图片存成blob,然后就遇到跨域卡住了(bgm38)
// js
fetch('https://lain.bgm.tv/r/100/pic/user/l/000/00/00/1.jpg')
// 会报一个跨域的错

fetch('https://api.bgm.tv/v0/users/sai/avatar?type=small')
// api 是在302重定向,相当于还是要请求lain.bgm.tv……

能不能,可不可以,也许,在 lain.bgm.tv 配个 Access-Control-Allow-Origin (bgm67)

还有用户脚本是不是遇到跨域一点辙都没有?
我现在能想到的解法都很(bgm102)
1. 手 动 保 存
2. 本 地 代 理 服 务 器
#2 - 2023-5-20 17:03
(天生万物以养人,人无一物以报天)
你都写用户脚本了,当然是直接绕过跨域请求啦

https://github.com/trim21/gm-fetch
#2-1 - 2023-5-20 18:19
=L=+
试了一下,直接用GM.xmlHttpRequest成功了,用GM_fetch遇到点bug
有解释为什么GM.xmlHttpRequest可以跨域的文章吗?
#2-2 - 2023-5-20 18:19
=L=+
// ==UserScript==
// @name         GM_fetch
// @match        *://bangumi.tv/*
// @require      https://cdn.jsdelivr.net/npm/@trim21/gm-fetch
// @grant        GM.xmlHttpRequest
// @connect      lain.bgm.tv
// ==/UserScript==

;(async () => {
    const res = await GM_fetch('https://lain.bgm.tv/r/100/pic/user/l/000/00/00/1.jpg')
    console.log('GM_fetch res', res) // res.rawBody里有正确的blob
    const blob = await res.blob() // 问题大概在这里
    console.log('GM_fetch blob', blob) // blob.size = 0
    {
        const img = document.createElement('img')
        img.src = URL.createObjectURL(blob)
        document.body.append(img)
    }
    {
        const img = document.createElement('img')
        img.src = URL.createObjectURL(res.rawBody)
        document.body.append(img)
    }
})()

GM.xmlHttpRequest({
    method: 'GET',
    url: 'https://lain.bgm.tv/r/100/pic/user/l/000/00/00/1.jpg',
    responseType: 'blob',
    onload: (res) => {
        console.log('GM.xmlHttpRequest', res.response)

        const img = document.createElement('img')
        img.src = URL.createObjectURL(res.response)
        document.body.append(img)
    },
})
#2-3 - 2023-5-20 18:26
=L=+
@name @grant
没裹code标签@出来了两个人(bgm38)
#2-4 - 2023-5-21 00:54
bangumi大西王
=L=+ 说: // ==UserScript==// @name         GM_fetch// @match    ...
看样子是我blob实现的有点问题
#2-5 - 2023-5-21 01:08
bangumi大西王
Trim21 说: 看样子是我blob实现的有点问题
修好了!
#3 - 2023-5-20 18:21
如果图片跨域,你可以使用CORS(跨域资源共享)来请求图片,并将其转换为blob对象。代码如下所示:
const img = new Image();
img.crossOrigin = 'anonymous';
img.src = 'https://example.com/image.jpg';
img.onload = () => {
  const canvas = document.createElement('canvas');
  canvas.width = img.width;
  canvas.height = img.height;
  const ctx = canvas.getContext('2d');
  ctx.drawImage(img, 0, 0);
  canvas.toBlob((blob) => {
    // 在这里使用blob对象
  });
};
这段代码首先创建一个Image对象,并将其crossOrigin属性设置为'anonymous',以便启用CORS。然后,我们设置Image对象的src属性为图片的URL。当图片加载完成后,我们创建一个canvas元素,并将其大小设置为图片的大小。接着,我们获取canvas的2D上下文,并使用drawImage方法将图片绘制到canvas上。最后,我们使用toBlob方法将canvas转换为blob对象,并在回调函数中使用该对象。
#3-1 - 2023-5-20 18:32
=L=+
gpt?
姑且试了一下
const img = new Image()
img.crossOrigin = 'anonymous'
img.src = 'https://lain.bgm.tv/r/100/pic/user/l/000/00/00/1.jpg'
img.onload = () => {
    const canvas = document.createElement('canvas')
    canvas.width = img.width
    canvas.height = img.height
    const ctx = canvas.getContext('2d')
    ctx.drawImage(img, 0, 0)
    canvas.toBlob((blob) => {
        console.log(blob)
    })
}
会报跨域的错
#3-2 - 2023-5-20 18:46
可乐呀
=L=+ 说: gpt?
姑且试了一下
const img = new Image()
img.crossOrigin = 'anonymous'
img.src = 'https://lain.bgm.tv/r/1...
是的,还需要服务端添加Access-Control-Allow-Origin,不CORS只是图片获取宽高是可以的,放到canvas必须CORS了(bgm38)