完成文件上传链接生成功能

This commit is contained in:
Kakune55 2023-12-19 17:31:30 +08:00
parent 42c764f825
commit ee9aeb4820
5 changed files with 218 additions and 19 deletions

1
.gitignore vendored Normal file
View File

@ -0,0 +1 @@
/data

138
Web/info.html Normal file
View File

@ -0,0 +1,138 @@
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>文件详细</title>
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/font-awesome/5.15.3/css/all.min.css">
<style>
body {
font-family: 'Arial', sans-serif;
background-color: #f5f5f5;
margin: 0;
padding: 0;
display: flex;
flex-direction: column;
align-items: center;
justify-content: center;
height: 100vh;
}
header {
background-color: #333;
color: #fff;
text-align: center;
width: 100%;
position: fixed;
top: 0;
left: 0;
}
#container {
width: 85%;
max-width: 800px;
background-color: #fff;
padding: 20px;
border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
margin-top: 80px;
/* 顶栏高度 + 20px 的间距 */
text-align: center;
}
#table-container {
display: flex;
width: 100%;
border-collapse: collapse;
}
#table-container table {
border: 1px solid #ddd;
border-radius: 5px;
box-shadow: 0 0 20px rgba(0, 0, 0, 0.15);
width: 100%;
}
#table-container tr:hover {
background-color: #f1f1f1;
}
#table-container td:first-child {
width: 20%;
height: 30px;
}
#table-container td:last-child {
width: 80%;
}
#imgshow {
width: 100%;
}
</style>
</head>
<body>
<header>
<h2>Pixel</h2>
<!-- 添加帮助和用户信息的按钮/链接等 -->
</header>
<div id="container">
<div id="thumbnail-container">
<img id="imgshow" alt="缩略图">
<hr>
<div id="table-container">
<table id="linktable">
<tr>
<td>URL</td>
<td><span class="imgurl"></span></td>
</tr>
<tr>
<td>MarkDown</td>
<td>![alt](<span class="imgurl"></span>)</td>
</tr>
<tr>
<td>HTML</td>
<td>&lt;img src="<span class="imgurl"></span>" alt="img" /&gt;
</td>
</tr>
<tr>
<td>HTML</td>
<td>[img]<span class="imgurl"></span>[/img]
</td>
</tr>
</table>
</div>
</div>
</div>
<script>
function GetRequest() {
var url = location.search; //获取url中"?"符后的字串
var theRequest = new Object();
if (url.indexOf("?") != -1) {
var str = url.substr(1);
strs = str.split("&");
for (var i = 0; i < strs.length; i++) {
theRequest[strs[i].split("=")[0]] = decodeURI(strs[i].split("=")[1]);
}
}
return theRequest;
}
const Resq = GetRequest();
linkid = Resq["id"]
imgurl = window.location.protocol + "//" + window.location.host + "/img?id=" + linkid
document.getElementById("imgshow").src = imgurl
var elements = document.getElementsByClassName("imgurl"); // 获取所有具有类名 "myClass" 的元素
for (var i = 0; i < elements.length; i++) {
elements[i].innerHTML = imgurl;
}
</script>
</body>
</html>

View File

@ -1,5 +1,6 @@
<!DOCTYPE html> <!DOCTYPE html>
<html lang="en"> <html lang="en">
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
@ -36,7 +37,8 @@
padding: 20px; padding: 20px;
border-radius: 8px; border-radius: 8px;
box-shadow: 0 0 10px rgba(0, 0, 0, 0.1); box-shadow: 0 0 10px rgba(0, 0, 0, 0.1);
margin-top: 80px; /* 顶栏高度 + 20px 的间距 */ margin-top: 80px;
/* 顶栏高度 + 20px 的间距 */
text-align: center; text-align: center;
} }
@ -54,7 +56,6 @@
background-color: #4caf50; background-color: #4caf50;
color: #fff; color: #fff;
border: none; border: none;
padding: 10px;
border-radius: 4px; border-radius: 4px;
cursor: pointer; cursor: pointer;
transition: background-color 0.3s; transition: background-color 0.3s;
@ -71,7 +72,6 @@
background-color: #4caf50; background-color: #4caf50;
color: #fff; color: #fff;
border: none; border: none;
padding: 10px;
border-radius: 4px; border-radius: 4px;
cursor: pointer; cursor: pointer;
transition: background-color 0.3s; transition: background-color 0.3s;
@ -99,7 +99,8 @@
margin-top: 20px; margin-top: 20px;
max-width: 100%; max-width: 100%;
height: auto; height: auto;
display: none; /* 默认隐藏 */ display: none;
/* 默认隐藏 */
} }
#thumbnail { #thumbnail {
@ -108,6 +109,7 @@
} }
</style> </style>
</head> </head>
<body> <body>
<header> <header>
@ -158,7 +160,8 @@
xhr.onreadystatechange = function () { xhr.onreadystatechange = function () {
if (xhr.readyState === XMLHttpRequest.DONE) { if (xhr.readyState === XMLHttpRequest.DONE) {
if (xhr.status === 200) { if (xhr.status === 200) {
alert('文件上传成功!'); gourl = "info?id=" + xhr.responseText
window.location.href = gourl
} else { } else {
alert('文件上传失败!'); alert('文件上传失败!');
} }
@ -198,4 +201,5 @@
</script> </script>
</body> </body>
</html>
</html>

View File

@ -18,7 +18,8 @@ func Initdb() {
createTableSQL := ` createTableSQL := `
CREATE TABLE IF NOT EXISTS mytable ( CREATE TABLE IF NOT EXISTS mytable (
link TEXT PRIMARY KEY, link TEXT PRIMARY KEY,
md5 TEXT NOT NULL md5 TEXT NOT NULL,
ext TEXT NOT NULL
); );
` `
@ -28,7 +29,7 @@ func Initdb() {
} }
} }
func NewFile(linkID string, md5 string) { func NewFile(linkID string, md5 string, ext string) {
db, err := sql.Open("sqlite3", "./data/database.db") db, err := sql.Open("sqlite3", "./data/database.db")
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
@ -37,7 +38,7 @@ func NewFile(linkID string, md5 string) {
// SQL语句 // SQL语句
SQL := ` SQL := `
INSERT INTO "main"."mytable" ("link", "md5") VALUES (?, ?) INSERT INTO "main"."mytable" ("link", "md5" ,"ext") VALUES (?, ? , ?)
` `
stmt, err := db.Prepare(SQL) stmt, err := db.Prepare(SQL)
@ -45,13 +46,13 @@ func NewFile(linkID string, md5 string) {
log.Fatal(err) log.Fatal(err)
} }
_, err = stmt.Exec(linkID,md5) //插入记录 _, err = stmt.Exec(linkID,md5,ext) //插入记录
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
} }
} }
func GetFileInfo(linkID string) string { func GetFileName(linkID string) string {
db, err := sql.Open("sqlite3", "./data/database.db") db, err := sql.Open("sqlite3", "./data/database.db")
if err != nil { if err != nil {
log.Fatal(err) log.Fatal(err)
@ -71,7 +72,8 @@ func GetFileInfo(linkID string) string {
// 扫描查询结果 // 扫描查询结果
var md5 string var md5 string
var linkIDx string var linkIDx string
err = row.Scan(&linkIDx,&md5) var ext string
err = row.Scan(&linkIDx,&md5,&ext)
if err != nil { if err != nil {
if err == sql.ErrNoRows { if err == sql.ErrNoRows {
return "" return ""
@ -80,5 +82,5 @@ func GetFileInfo(linkID string) string {
} }
return "" return ""
} }
return md5 return md5+ext
} }

66
main.go
View File

@ -11,6 +11,7 @@ import (
"net/http" "net/http"
"os" "os"
"path" "path"
"path/filepath"
"strconv" "strconv"
"time" "time"
) )
@ -31,7 +32,6 @@ func init() {
` `
fmt.Println(appinfo) fmt.Println(appinfo)
database.Initdb() //初始化数据库
dirPath := "./data/img" dirPath := "./data/img"
// 使用 os.Stat 检查目录是否存在 // 使用 os.Stat 检查目录是否存在
@ -39,7 +39,7 @@ func init() {
if os.IsNotExist(err) { if os.IsNotExist(err) {
// 目录不存在,可以调用 os.Mkdir 创建 // 目录不存在,可以调用 os.Mkdir 创建
err := os.Mkdir(dirPath, 0755) err := os.MkdirAll(dirPath, 0755)
if err != nil { if err != nil {
fmt.Println("无法创建目录:", err) fmt.Println("无法创建目录:", err)
return return
@ -52,18 +52,28 @@ func init() {
// 发生其他错误 // 发生其他错误
fmt.Println("发生错误:", err) fmt.Println("发生错误:", err)
} }
database.Initdb() //初始化数据库
fmt.Println("数据库初始化完成")
} }
func main() { func main() {
http.HandleFunc("/info", showimg)
http.HandleFunc("/upload", upload) //设置访问的路由 http.HandleFunc("/upload", upload)
http.HandleFunc("/img/",downloadHandler)//设置访问的路由
fmt.Println("Web服务器已启动")
err := http.ListenAndServe(":9090", nil) //设置监听的端口 err := http.ListenAndServe(":9090", nil) //设置监听的端口
if err != nil { if err != nil {
log.Fatal("ListenAndServe: ", err) log.Fatal("ListenAndServe: ", err)
} }
} }
func showimg(w http.ResponseWriter, r *http.Request) {
t, _ := template.ParseFiles("Web/info.html")
t.Execute(w, "Hello")
}
// 处理/upload 逻辑 // 处理/upload 逻辑
func upload(w http.ResponseWriter, r *http.Request) { func upload(w http.ResponseWriter, r *http.Request) {
@ -116,8 +126,9 @@ func upload(w http.ResponseWriter, r *http.Request) {
io.Copy(f, file) io.Copy(f, file)
// 存入数据库 // 存入数据库
database.NewFile(RandomString(10),md5sum) var linkid = RandomString(10)
database.NewFile(linkid,md5sum,ext)
w.Write([]byte(linkid))
} }
} }
@ -131,3 +142,46 @@ func RandomString(n int) string {
} }
return string(bytes) return string(bytes)
} }
func downloadHandler(w http.ResponseWriter, r *http.Request) {
// 获取请求参数,例如文件名
filename := r.FormValue("id")
if filename == "" {
http.Error(w, "未提供文件名", http.StatusBadRequest)
return
}
// 拼接文件路径,确保路径安全性
filePath := filepath.Join("./data/img", database.GetFileName(filename))
// 打开文件
file, err := os.Open(filePath)
if err != nil {
http.Error(w, "文件未找到", http.StatusNotFound)
return
}
defer file.Close()
// 获取文件信息
fileInfo, err := file.Stat()
if err != nil {
http.Error(w, "无法获取文件信息", http.StatusInternalServerError)
return
}
// 设置响应头,告诉浏览器直接显示文件
w.Header().Set("Content-Disposition", "inline; filename="+filename)
w.Header().Set("Content-Type", "image/jpeg") // 适用于 JPEG 图片,根据实际文件类型设置
// 将文件内容拷贝到响应体中
http.ServeContent(w, r, filename, fileInfo.ModTime(), file)
}
// 辅助函数,获取文件大小
func fileSize(file *os.File) int64 {
stat, err := file.Stat()
if err != nil {
return 0
}
return stat.Size()
}