mirror of
https://github.com/Kakune55/Pixel.git
synced 2025-05-06 18:29:25 +08:00
完成文件上传链接生成功能
This commit is contained in:
parent
42c764f825
commit
ee9aeb4820
1
.gitignore
vendored
Normal file
1
.gitignore
vendored
Normal file
@ -0,0 +1 @@
|
|||||||
|
/data
|
138
Web/info.html
Normal file
138
Web/info.html
Normal 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></td>
|
||||||
|
</tr>
|
||||||
|
<tr>
|
||||||
|
<td>HTML</td>
|
||||||
|
<td><img src="<span class="imgurl"></span>" alt="img" />
|
||||||
|
</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>
|
@ -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>
|
@ -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
66
main.go
@ -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()
|
||||||
|
}
|
||||||
|
Loading…
x
Reference in New Issue
Block a user