1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
|
package main
import (
"compress/gzip"
"errors"
"fmt"
"io"
"net/http"
"net/url"
"os"
"os/exec"
"os/user"
"path/filepath"
"regexp"
"strings"
"fyne.io/fyne/v2"
"fyne.io/fyne/v2/app"
"fyne.io/fyne/v2/container"
"fyne.io/fyne/v2/dialog"
"fyne.io/fyne/v2/theme"
"fyne.io/fyne/v2/widget"
)
var (
base_url string
isValidUrl bool
myApp fyne.App
myWindow fyne.Window
// 创建一个 HTTP 客户端
client = &http.Client{}
)
var appICON = &fyne.StaticResource{
StaticName: "pdf.ico",
StaticContent: []byte("\x00"),
}
var windowICON = &fyne.StaticResource{
StaticName: "PDF.png",
StaticContent: []byte("\x89PNG"),
}
func init() {
fontPath := "C:\\Windows\\Fonts\\SIMYOU.TTF"
os.Setenv("FYNE_FONT", fontPath)
myApp = app.New()
myWindow = myApp.NewWindow("PDF_Downloader")
// 设置默认窗口大小
myWindow.Resize(fyne.NewSize(800, 100)) // 这里可以设置为您想要的尺寸
}
func main() {
// 尝试使用嵌入的图标
// iconResource := fyne.NewStaticResource("PDFIcon", icon)
myWindow.SetIcon(windowICON)
myApp.SetIcon(appICON)
label_input := widget.NewLabel("在下面输入网址:")
label_status := widget.NewLabel("")
entry := widget.NewMultiLineEntry()
entry.SetPlaceHolder("我这里很空...") //
// entry.SetText("我这里好空...")
button := widget.NewButtonWithIcon("下载", theme.DownloadIcon(), func() {
go funcForDownloadBTN(entry.Text, label_status, myWindow)
})
// 创建一个水平布局的容器,将按钮放在中间
buttonContainer := container.NewHBox(button, label_status)
// 将所有组件垂直排列
content := container.NewVBox(
label_input,
entry,
buttonContainer, // 使用按钮容器代替直接放置按钮
)
myWindow.SetContent(content)
myWindow.ShowAndRun()
}
// 验证 URL 是否有效,并返回基本 url
func isValidURL(u string) (bool, string) {
parsedURL, err := url.ParseRequestURI(u)
if err != nil {
fmt.Println("Error parsing URL:", err)
return false, ""
} else if err == nil {
base_url := parsedURL.Scheme + "://" + parsedURL.Host
return true, base_url
}
return false, ""
}
func fetchHtml(pageURL string) (string, error) {
// 创建一个 HTTP 客户端
client := &http.Client{}
// 创建一个请求
req, err := http.NewRequest("GET", pageURL, nil)
if err != nil {
dialog.ShowError(errors.New("发生意外"+err.Error()), myWindow)
}
// 添加自定义的头部
req.Header.Set("Proxy-Connection", "keep-alive")
req.Header.Set("Cache-Control", "max-age=0")
req.Header.Set("Upgrade-Insecure-Requests", "1")
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.75 Safari/537.36")
req.Header.Set("Accept", "text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,image/apng,*/*;q=0.8")
req.Header.Set("Accept-Encoding", "gzip, deflate")
// 添加 Cookie
// 如果你有多个 Cookie 需要添加,可以重复这个步骤
req.AddCookie(&http.Cookie{Name: "YourCookieName", Value: "YourCookieValue"})
// 使用自定义的请求进行 HTTP 调用
resp, err := client.Do(req)
if err != nil {
dialog.ShowError(errors.New("发生意外"+err.Error()), myWindow)
}
// 检查响应头部中的 Content-Encoding 字段来判断内容是否被压缩
contentEncoding := resp.Header.Get("Content-Encoding")
// 根据 Content-Encoding 解压内容
var reader io.ReadCloser
switch {
case strings.Contains(contentEncoding, "gzip"):
// 如果内容是gzip压缩的,则使用gzip.Reader解压
var err error
reader, err = gzip.NewReader(resp.Body)
if err != nil {
dialog.ShowError(errors.New("发生意外"+err.Error()), myWindow)
}
default:
// 如果内容没有压缩,则直接使用响应体
reader = resp.Body
}
defer reader.Close()
// 读取响应内容
html, err := io.ReadAll(reader)
if err != nil {
dialog.ShowError(errors.New("发生意外"+err.Error()), myWindow)
}
// 打印 HTML 内容
// fmt.Println(string(html))
return string(html), nil
}
func DownloadAndSavePDF(base_url, src_url, Title string, label_status *widget.Label) {
label_status.SetText("正在下载,请稍后...")
// 发起 HTTP GET 请求
// 创建一个请求
pdfurl := base_url + strings.Split(src_url, "=")[1]
req, err := http.NewRequest("GET", pdfurl, nil)
if err != nil {
dialog.ShowError(errors.New("发生意外"+err.Error()), myWindow)
}
// 添加自定义的头部
req.Header.Set("Referer", base_url+src_url)
req.Header.Set("User-Agent", "Mozilla/5.0 (Windows NT 6.1) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/68.0.3440.75 Safari/537.36")
// 添加 Cookie
// 如果你有多个 Cookie 需要添加,可以重复这个步骤
// req.AddCookie(&http.Cookie{Name: "YourCookieName", Value: "YourCookieValue"})
// 使用自定义的请求进行 HTTP 调用
resp, err := client.Do(req)
if err != nil {
// fmt.Println("line 217:", err)
dialog.ShowError(errors.New("发生意外"+err.Error()), myWindow)
// return ""
}
defer resp.Body.Close()
// 检查响应头部中的 Content-Encoding 字段来判断内容是否被压缩
contentEncoding := resp.Header.Get("Content-Encoding")
// 根据 Content-Encoding 解压内容
var reader io.ReadCloser
switch {
case strings.Contains(contentEncoding, "gzip"):
// 如果内容是gzip压缩的,则使用gzip.Reader解压
var err error
reader, err = gzip.NewReader(resp.Body)
if err != nil {
dialog.ShowError(errors.New("发生意外"+err.Error()), myWindow)
}
default:
// 如果内容没有压缩,则直接使用响应体
reader = resp.Body
}
defer reader.Close()
// 构建桌面路径
// 获取当前用户信息
currentUser, _ := user.Current()
desktopPath := filepath.Join(currentUser.HomeDir, "Desktop")
// timenmae := time.Now().Format("20060102_1504")
pdfFileFullPath := desktopPath + "\\" + Title + ".pdf"
// 创建本地文件
file, err := os.Create(pdfFileFullPath)
if err != nil {
fmt.Println("line 231:", err)
dialog.ShowError(errors.New("发生意外"+err.Error()), myWindow)
}
defer file.Close()
// 将响应内容写入文件
_, err = io.Copy(file, reader)
if err != nil {
fmt.Println("line 239:", err)
dialog.ShowError(errors.New("发生意外"+err.Error()), myWindow)
}
label_status.SetText("文件下载成功,保存在\"" + pdfFileFullPath + "\",已打开并聚焦,注意新打开文件管理器。")
// return pdfFileFullPath
LocatFile(pdfFileFullPath)
}
func extract_SrcUrl(html_str string) string {
re := regexp.MustCompile(`(?i)<iframe[^>]+src\s*=\s*["']([^"']+)["']`)
match := re.FindStringSubmatch(string(html_str))
if len(match) >= 2 {
return match[1]
}
return ""
}
func extract_Title(html_str string) string {
re := regexp.MustCompile(`(?s)<td[^>]*class="wz_title"[^>]*>(.*?)<\/td>`)
match := re.FindStringSubmatch(html_str)
if len(match) >= 2 {
return match[1]
}
return ""
}
func funcForDownloadBTN(inputText string, label_status *widget.Label, myWindow fyne.Window) {
// fmt.Println(inputText)
isValidUrl, base_url = isValidURL(inputText)
if isValidUrl {
html, _ := fetchHtml(inputText)
SrcUrl := extract_SrcUrl(html)
Title := extract_Title(html)
if SrcUrl != "" {
DownloadAndSavePDF(base_url, SrcUrl, Title, label_status)
} else {
dialog.ShowError(errors.New("该网页中无PDF文件链接!"), myWindow)
label_status.SetText("")
}
} else {
dialog.ShowError(errors.New("请输入正确的网址。"), myWindow)
}
}
func LocatFile(filePath string) {
// Windows Explorer 需要的参数是文件的目录
dir := filepath.Dir(filePath)
// 构造并执行命令
cmd := exec.Command("explorer", "/select,", filePath)
cmd.Dir = dir
if err := cmd.Start(); err != nil {
panic(err)
}
}
|