在github发布中使用资产来修改github页面网站



我正在制作一个网站来显示我所拥有的项目。大约每周一次,这个项目会生成一个新的版本,文件名为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下载它?

所以我找到了一个解决方案,虽然它不是很好。我最后给dpaste.com的维护者发了消息,他非常友好地启用了CORS,所以我现在可以将我的文件上传到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-release的个人分支的版本描述中包含了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}))
}

最新更新