javascript 在github版本中使用asset修改github pages网站

8fsztsew  于 2023-04-10  发布在  Java
关注(0)|答案(1)|浏览(150)

我正在制作一个网站来展示我的一个项目。大约每周一次,这个项目生成一个新的版本,其中有一个文件machine_friendly.csv。这个文件只包含一些生成的数据(每次都不同)。
我想创建一个github页面网站,用户可以导航到该网站并查看machine_friendly.csv文件的美化版本。问题是github的CORS不允许我直接下载该文件。例如,这不起作用:

React.useEffect(() => {
    fetch('https://github.com/beyarkay/eskom-calendar/releases/download/latest/machine_friendly.csv')
    .then(response => {
        if (response.ok) return response.json()
        throw new Error('Network response was not ok.')
    })
    .then(data => console.log(data.contents))
    .catch(err => console.log(err));
}, []);

并给出CORS错误消息:

Cross-Origin Request Blocked: The Same Origin Policy disallows reading the remote resource at 
https://github.com/beyarkay/eskom-calendar/releases/download/latest/machine_friendly.csv. 
(Reason: CORS header ‘Access-Control-Allow-Origin’ missing). 
Status code: 302.

有什么办法可以解决这个问题吗?我试过将文件上传到pastebin和github版本,但没有一个pastebin可以免费启用CORS。我也试过一些CORS代理,但它们要么太长时间,要么就不再工作了。我也试过使用github的API,但这也给CORS带来了问题。
是否有在线服务,我可以上传我的小(〈1MB)文件,并通过javascript下载它?

nnsrf1az

nnsrf1az1#

所以我找到了一个解决方案,虽然不是很好,我最后给dpaste.com的维护者发了消息,所以我现在可以把我的文件上传到dpaste并再次下载。
我得到的GH操作看起来像这样:

jobs:
  build-and-publish-calendars:
    runs-on: ubuntu-latest
    steps:
    ...
    - name: POST machine_friendly.csv to dpaste.org
      run: |
        cat calendars/machine_friendly.csv | curl -X POST -F "expires=31536000" -F 'format=url' -F 'content=<-' https://dpaste.org/api/ > pastebin.txt

    - name: Write pastebin link to GH variable
      run: |
        echo "pastebin=$(cat pastebin.txt)/raw" >> $GITHUB_OUTPUT
      id: PASTEBIN

然后稍后(时髦的黑客入侵)我使用IsaacShelton/update-existing-releasepersonal fork在我的版本描述中包含pastebin链接(我维护个人分支以进行一些与此问题无关的性能改进)。步骤如下:

...
    - name: Update latest release with new calendars
      uses: beyarkay/update-existing-release@master
      with:
        token: ${{ secrets.GH_ACTIONS_PAT }}
        release: My Updated Release
        updateTag: true
        tag: latest
        replace: true
        files: ${{ steps.LS-CALENDARS.outputs.LS_CALENDARS }}
        body: "If you encounter CORS issues, you'll need to use this [pastebin link](${{ steps.PASTEBIN.outputs.pastebin }})"

在我的网站上,我有一个片段,比如:

const downloadFromRelease = async () => {

    // We need octokit in order to download the metadata about the release
    const octokit = new Octokit({
        auth: process.env.GH_PAGES_ENV_PAT || process.env.GH_PAGES_PAT
    })
    const desc = await octokit.request("GET /repos/beyarkay/eskom-calendar/releases/72143886", {
        owner: "beyarkay",
        repo: "eskom-calendar",
        release_id: "72143886"
    }).then((res) => res.data.body)

    // Here's some regex that matches the markdown formatted link
    const pastebin_re = /\[pastebin link\]\((https:\/\/dpaste\.org\/(\w+)\/raw)\)/gm
    const match = desc.match(pastebin_re)

    // Now that we've got a match, query that URL to get the data
    const url = match[0].replace("[pastebin link](", "").replace(")", "")
    console.log(`Fetching data from ${url}`)
    return fetch(url)
        .then(res => res.text())
        .then(newEvents => {
            // And finally parse the URL data into Event objects
            const events: Event[] = newEvents.split("\n").map( line => ( {
                area_name: line.split(",")[0],
                start:  line.split(",")[1],
                finsh:  line.split(",")[2],
                stage:  line.split(",")[3],
                source: line.split(",")[4],
            }))
            return events
        })
}

把所有这些结合在一起,我可以使用这个片段来实际执行react中的setState

// Define a Result type that represents data which might not be ready yet
    type Result<T, E> = { state: "unsent" }
        | { state: "loading" }
        | { state: "ready", content: T }
        | { state: "error", content: E }
    // The events start out as being "unsent"
    const [events, setEvents] =
        React.useState<Result<Event[], string>>( { state: "unsent" })

    // If they're unsent, then send off the request
    if (events.state === "unsent") {
        downloadMachineFriendly().then(newEvents => {

            // When the data comes back, use the `setEvents` hook
            setEvents({
                state: "ready",
                content: newEvents,
            })

        // If there's an error, store the error
        }).catch(err => setEvents({state: "error", content: err}))
    }

相关问题