mirror of
https://github.com/Kakune55/Pixel.git
synced 2025-05-06 18:29:25 +08:00
233 lines
6.0 KiB
Go
233 lines
6.0 KiB
Go
package main
|
||
|
||
import (
|
||
"Pixel/database"
|
||
"crypto/md5"
|
||
"fmt"
|
||
"html/template"
|
||
"image"
|
||
"io"
|
||
"log"
|
||
"math/rand"
|
||
"net/http"
|
||
"os"
|
||
"path"
|
||
"path/filepath"
|
||
"strconv"
|
||
"time"
|
||
|
||
"github.com/disintegration/imaging"
|
||
)
|
||
|
||
|
||
func init() {
|
||
const appinfo string = `
|
||
|
||
______ ________ ______ __ __ __
|
||
/_____/\ /_______/\ /_____/\ /__/\ /__/\ /_/\
|
||
\:::_ \ \ \__.::._\/ \::::_\/_ \ \::\\:.\ \ \:\ \
|
||
\:(_) \ \ \::\ \ \:\/___/\ \_\::_\:_\/ \:\ \
|
||
\: ___\/ _\::\ \__ \::___\/_ _\/__\_\_/\ \:\ \____
|
||
\ \ \ /__\::\__/\ \:\____/\ \ \ \ \::\ \ \:\/___/\
|
||
\_\/ \________\/ \_____\/ \_\/ \__\/ \_____\/
|
||
|
||
|
||
`
|
||
fmt.Println(appinfo)
|
||
|
||
dirPath := "./data/img"
|
||
|
||
// 使用 os.Stat 检查目录是否存在
|
||
_, err := os.Stat(dirPath)
|
||
|
||
if os.IsNotExist(err) {
|
||
// 目录不存在,可以调用 os.Mkdir 创建
|
||
err := os.MkdirAll(dirPath, 0755)
|
||
if err != nil {
|
||
fmt.Println("无法创建目录:", err)
|
||
return
|
||
}
|
||
fmt.Println("目录创建成功:", dirPath)
|
||
} else if err == nil {
|
||
// 目录已存在
|
||
fmt.Println("目录已存在:", dirPath)
|
||
} else {
|
||
// 发生其他错误
|
||
fmt.Println("发生错误:", err)
|
||
}
|
||
|
||
database.Initdb() //初始化数据库
|
||
fmt.Println("数据库初始化完成")
|
||
}
|
||
|
||
|
||
func main() {
|
||
http.HandleFunc("/info", showimg)
|
||
http.HandleFunc("/upload", upload)
|
||
http.HandleFunc("/img/",downloadHandler)//设置访问的路由
|
||
http.HandleFunc("/img/mini",displayThumbnailHandler)
|
||
fmt.Println("Web服务器已启动")
|
||
err := http.ListenAndServe(":9090", nil) //设置监听的端口
|
||
if err != nil {
|
||
log.Fatal("ListenAndServe: ", err)
|
||
}
|
||
}
|
||
|
||
func showimg(w http.ResponseWriter, r *http.Request) {
|
||
t, _ := template.ParseFiles("Web/info.html")
|
||
t.Execute(w, "Hello")
|
||
}
|
||
|
||
|
||
// 处理/upload 逻辑
|
||
func upload(w http.ResponseWriter, r *http.Request) {
|
||
fmt.Println("method:", r.Method) // 获取请求的方法
|
||
|
||
if r.Method == "GET" { // 前端页面渲染
|
||
crutime := time.Now().Unix()
|
||
h := md5.New()
|
||
io.WriteString(h, strconv.FormatInt(crutime, 10))
|
||
token := fmt.Sprintf("%x", h.Sum(nil))
|
||
|
||
t, _ := template.ParseFiles("Web/upload.html")
|
||
t.Execute(w, token)
|
||
} else { // 后端POST接收逻辑
|
||
r.ParseMultipartForm(32 << 20)
|
||
file, handler, err := r.FormFile("file")
|
||
if err != nil {
|
||
fmt.Println(err)
|
||
return
|
||
}
|
||
defer file.Close()
|
||
|
||
// 生成文件的MD5哈希
|
||
h := md5.New()
|
||
if _, err := io.Copy(h, file); err != nil {
|
||
fmt.Println(err)
|
||
return
|
||
}
|
||
md5sum := fmt.Sprintf("%x", h.Sum(nil))
|
||
|
||
// 获取文件扩展名
|
||
fname := handler.Filename
|
||
ext := path.Ext(fname)
|
||
|
||
// 创建新文件,使用MD5哈希和原始扩展名
|
||
newFilename := md5sum + ext
|
||
f, err := os.OpenFile("./data/img/"+newFilename, os.O_WRONLY|os.O_CREATE, 0666)
|
||
if err != nil {
|
||
fmt.Println(err)
|
||
return
|
||
}
|
||
defer f.Close()
|
||
|
||
// 将文件内容拷贝到新文件
|
||
_, err = file.Seek(0, 0)
|
||
if err != nil {
|
||
fmt.Println(err)
|
||
return
|
||
}
|
||
io.Copy(f, file)
|
||
|
||
// 存入数据库
|
||
var linkid = RandomString(10)
|
||
database.NewFile(linkid,md5sum,ext)
|
||
w.Write([]byte(linkid))
|
||
}
|
||
}
|
||
|
||
|
||
func RandomString(n int) string {
|
||
const letters = "0123456789ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz"
|
||
bytes := make([]byte, n)
|
||
rand.Seed(time.Now().UnixNano())
|
||
for i := 0; i < n; i++ {
|
||
bytes[i] = letters[rand.Intn(len(letters))]
|
||
}
|
||
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()
|
||
}
|
||
|
||
func generateThumbnail(filePath string, width, height int) (*image.NRGBA, error) {
|
||
// 打开图像文件
|
||
img, err := imaging.Open(filePath)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
|
||
// 调整图像大小以创建缩略图
|
||
thumbnail := imaging.Resize(img, width, height, imaging.Lanczos)
|
||
|
||
return thumbnail, nil
|
||
}
|
||
|
||
func displayThumbnailHandler(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))
|
||
|
||
// 生成缩略图
|
||
thumbnail, err := generateThumbnail(filePath, 128, 0) // 设置缩略图的宽度和高度
|
||
if err != nil {
|
||
http.Error(w, "无法生成缩略图", http.StatusInternalServerError)
|
||
return
|
||
}
|
||
|
||
// 设置响应头,指示这是一张图像
|
||
w.Header().Set("Content-Type", "image/jpeg") // 使用 JPEG 格式或根据需要调整
|
||
|
||
// 将缩略图写入响应体
|
||
if err := imaging.Encode(w, thumbnail, imaging.JPEG); err != nil {
|
||
http.Error(w, "无法编码图像", http.StatusInternalServerError)
|
||
return
|
||
}
|
||
}
|