fix(download): 修复文件下载和错误处理功能
- 添加了对 text/plain 和 application/zip 格式的支持 - 在详情页面增加了 URL 输出调试信息 - 修复了跳转页面时的 URL 和 referer 处理逻辑 - 添加了下载失败时的错误事件推送和提示 - 在前端实现了错误消息的类型区分和显示 - 优化了侧边栏菜单组件的配置参数
This commit is contained in:
@@ -39,9 +39,11 @@ class BookService:
|
|||||||
print(f"文件夹:{name} 已存在")
|
print(f"文件夹:{name} 已存在")
|
||||||
|
|
||||||
def isDownloadTarget(self, soup): # 是否是可以下载的文件
|
def isDownloadTarget(self, soup): # 是否是可以下载的文件
|
||||||
return soup.headers.get('Content-Type') in ['"application/octet-stream"', "application/octet-stream"]
|
return soup.headers.get('Content-Type') in ['"application/octet-stream"', "application/octet-stream",
|
||||||
|
"text/plain","application/zip"]
|
||||||
|
|
||||||
def post_page(self, name, url): # 帖子页面
|
def post_page(self, name, url): # 帖子页面
|
||||||
|
print(f"详情页面 {self.setting["baseUrl"]}{url}")
|
||||||
response = requests.get(f"{self.setting["baseUrl"]}{url}", headers=self.headers)
|
response = requests.get(f"{self.setting["baseUrl"]}{url}", headers=self.headers)
|
||||||
print(f"详情页面状态码:{str(response.status_code)}")
|
print(f"详情页面状态码:{str(response.status_code)}")
|
||||||
soup = BeautifulSoup(response.text, 'lxml')
|
soup = BeautifulSoup(response.text, 'lxml')
|
||||||
@@ -66,17 +68,20 @@ class BookService:
|
|||||||
def download_file(self, file_url, dir_name, file_name): # 下载文件
|
def download_file(self, file_url, dir_name, file_name): # 下载文件
|
||||||
file_res = requests.get(file_url, headers=self.headers, stream=True, allow_redirects=False)
|
file_res = requests.get(file_url, headers=self.headers, stream=True, allow_redirects=False)
|
||||||
if file_res.status_code in (301, 302, 307, 308): # 非200状态码,重新请求
|
if file_res.status_code in (301, 302, 307, 308): # 非200状态码,重新请求
|
||||||
location = file_res.headers["location"]
|
file_url = file_res.headers["location"]
|
||||||
print(f'跳转页面了:{location}')
|
print(f'跳转页面了:{file_url}')
|
||||||
file_res = requests.get(location, headers={"referer": location}, stream=True)
|
file_res = requests.get(file_url, headers={"referer": file_url}, stream=True)
|
||||||
print(f"下载状态码:{file_res.status_code} {file_url}")
|
print(f"下载状态码:{file_res.status_code} {file_url}")
|
||||||
print(dir_name + "/" + file_name)
|
print(dir_name + "/" + file_name)
|
||||||
yield f"data: {self.setting["targetDate"]} {file_name}\n\n"
|
|
||||||
if self.isDownloadTarget(file_res):
|
if self.isDownloadTarget(file_res):
|
||||||
with open(f"download/{self.setting["targetDate"]}/{dir_name}/{file_name}", 'wb') as file2:
|
with open(f"download/{self.setting["targetDate"]}/{dir_name}/{file_name}", 'wb') as file2:
|
||||||
for chunk in file_res.iter_content(chunk_size=1024):
|
for chunk in file_res.iter_content(chunk_size=1024):
|
||||||
if chunk:
|
if chunk:
|
||||||
file2.write(chunk)
|
file2.write(chunk)
|
||||||
|
yield f"data: {self.setting["targetDate"]} {file_name}\n\n"
|
||||||
|
else:
|
||||||
|
yield f"event: mes_error\ndata: {self.setting["targetDate"]} {file_name}\n\n"
|
||||||
|
print("不是可下载文件")
|
||||||
|
|
||||||
def section_page(self, page): # 版块页面
|
def section_page(self, page): # 版块页面
|
||||||
print(f"当前页面 {page}")
|
print(f"当前页面 {page}")
|
||||||
@@ -105,11 +110,13 @@ class BookService:
|
|||||||
posts_max_timestamp = datetime_to_timestamp(self.get_post_date(posts[-1])) # 帖子列表最大时间戳
|
posts_max_timestamp = datetime_to_timestamp(self.get_post_date(posts[-1])) # 帖子列表最大时间戳
|
||||||
|
|
||||||
# 本页最早的帖子时间戳小于等于目标时间戳 且 倒计时页数大于 0 则跳转到上一页继续查找
|
# 本页最早的帖子时间戳小于等于目标时间戳 且 倒计时页数大于 0 则跳转到上一页继续查找
|
||||||
if posts_min_timestamp >= target_date_timestamp and not self.one_date_loading and self.setting["targetCountdownPage"] > 0:
|
if posts_min_timestamp >= target_date_timestamp and not self.one_date_loading and self.setting[
|
||||||
|
"targetCountdownPage"] > 0:
|
||||||
print("跳转到上一页")
|
print("跳转到上一页")
|
||||||
# yield f"data: 跳转到上一页\n\n"
|
# yield f"data: 跳转到上一页\n\n"
|
||||||
self.setting["targetCountdownPage"] = max(self.setting["targetCountdownPage"] - 1, 0)
|
self.setting["targetCountdownPage"] = max(self.setting["targetCountdownPage"] - 1, 0)
|
||||||
Setting.query.filter_by(name="book_download").update({"targetCountdownPage": self.setting["targetCountdownPage"]})
|
Setting.query.filter_by(name="book_download").update(
|
||||||
|
{"targetCountdownPage": self.setting["targetCountdownPage"]})
|
||||||
db.session.commit()
|
db.session.commit()
|
||||||
yield from self.section_page(self.setting["totalPage"] - self.setting["targetCountdownPage"])
|
yield from self.section_page(self.setting["totalPage"] - self.setting["targetCountdownPage"])
|
||||||
return None
|
return None
|
||||||
|
|||||||
@@ -10,11 +10,7 @@ const {isCollapse} = storeToRefs(isCollapseStore)
|
|||||||
<template>
|
<template>
|
||||||
<el-aside :width="!isCollapse?'200px':'auto'">
|
<el-aside :width="!isCollapse?'200px':'auto'">
|
||||||
<el-scrollbar>
|
<el-scrollbar>
|
||||||
<el-menu
|
<el-menu default-active="2" :collapse="isCollapse" router>
|
||||||
default-active="2"
|
|
||||||
:collapse="isCollapse"
|
|
||||||
class="el-menu-vertical-demo"
|
|
||||||
router>
|
|
||||||
<el-menu-item index="1" route="index">
|
<el-menu-item index="1" route="index">
|
||||||
<el-icon>
|
<el-icon>
|
||||||
<Menu/>
|
<Menu/>
|
||||||
|
|||||||
@@ -14,7 +14,8 @@ import {
|
|||||||
// 警告项接口
|
// 警告项接口
|
||||||
interface messageItem {
|
interface messageItem {
|
||||||
id: number
|
id: number
|
||||||
text: string
|
text: string,
|
||||||
|
type?: "success" | "error" | "warning" | "info" | "default"
|
||||||
}
|
}
|
||||||
|
|
||||||
interface BtnItem {
|
interface BtnItem {
|
||||||
@@ -89,12 +90,19 @@ const connect = (url: string) => {
|
|||||||
closeConnection()
|
closeConnection()
|
||||||
})
|
})
|
||||||
// 错误处理
|
// 错误处理
|
||||||
eventSource.addEventListener('error', () => {
|
// eventSource.addEventListener('error', () => {
|
||||||
console.log('连接断开或失败', new Date());
|
// console.log('连接断开或失败', new Date());
|
||||||
// 如果这里也频繁触发,确认了是断连重连
|
// // 如果这里也频繁触发,确认了是断连重连
|
||||||
if (eventSource.readyState === EventSource.CLOSED) {
|
// if (eventSource.readyState === EventSource.CLOSED) {
|
||||||
console.log('状态为 CLOSED');
|
// console.log('状态为 CLOSED');
|
||||||
}
|
// }
|
||||||
|
// })
|
||||||
|
eventSource.addEventListener('mes_error', (event) => {
|
||||||
|
messages.value.unshift({
|
||||||
|
id: Date.now() + messages.value.length,
|
||||||
|
text: event.data,
|
||||||
|
type: "error"
|
||||||
|
})
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
const closeConnection = () => {
|
const closeConnection = () => {
|
||||||
@@ -116,7 +124,7 @@ onUnmounted(() => {
|
|||||||
<template #default>
|
<template #default>
|
||||||
<div v-loading="loading" :style="{height: '100%'}">
|
<div v-loading="loading" :style="{height: '100%'}">
|
||||||
<el-alert v-for="item in messages" :key="item.id" :title="item.text"
|
<el-alert v-for="item in messages" :key="item.id" :title="item.text"
|
||||||
type="primary"
|
:type="item.type?item.type:'primary'"
|
||||||
@close="closeAlert(item.id)"/>
|
@close="closeAlert(item.id)"/>
|
||||||
</div>
|
</div>
|
||||||
</template>
|
</template>
|
||||||
|
|||||||
Binary file not shown.
Reference in New Issue
Block a user