提交文件api还需要完善

This commit is contained in:
2025-06-30 18:42:39 +08:00
parent 18c2cb9d4a
commit a6e4d6e219
5 changed files with 191 additions and 110 deletions
+37 -6
View File
@@ -11,20 +11,51 @@ import (
"saas/models"
"github.com/gin-gonic/gin"
"github.com/mitchellh/mapstructure"
)
func V1_file_api(r *gin.RouterGroup) {
r.GET("/", func(ctx *gin.Context) {
ctx.JSON(http.StatusOK, map[string]interface{}{
"error": "you need use Post",
Return_json(ctx, "json_error", nil)
})
})
r.POST("/upload", func(ctx *gin.Context) {
//文件api是一定要登录的,直接用中间件判断登录状态
// r.Use(func(ctx *gin.Context) {
// Use_is_login(ctx)
// })
r.Use(func(ctx *gin.Context) {
fmt.Println("file_api")
cookie := ctx.PostForm("cookie")
var cookie_t models.Cookie
if err := mapstructure.Decode(cookie, &cookie_t); err == nil {
if cookie_t.Value != "" {
cookie_vel := cookie_t.Value
fmt.Println(cookie_vel)
}
}
//fmt.Println(cookie)
file, err := ctx.FormFile("file")
if err == nil {
dst := path.Join("./data/upload", file.Filename)
ctx.SaveUploadedFile(file, dst)
fmt.Println(file)
} else {
fmt.Println(err)
}
})
r.POST("/upload", func(ctx *gin.Context) {
//先判断有没有登录
//获取中间件处理的结果
_, is_login := ctx.Get("user_info")
if is_login {
Return_json(ctx, "api_ok", nil)
} else {
Return_json(ctx, "user_no_sign", nil)
}
})
//接收头像的接口,
+3 -4
View File
@@ -1,7 +1,6 @@
package routers
import (
"fmt"
"saas/models"
"strings"
"time"
@@ -157,9 +156,9 @@ func V1_user_api(r *gin.RouterGroup) {
//先判断是否已经登录
//获取中间件处理的结果
user_info, is_login := ctx.Get("user_info")
fmt.Println(is_login)
fmt.Println(user_info)
_, is_login := ctx.Get("user_info")
//fmt.Println(is_login)
//fmt.Println(user_info)
if is_login == true {
//fmt.Println("loged")
cookie_any, _ := ctx.Get("cookie") //这个cookie在中间件已经判断为有效的,否则is_login不可能为true,所以直接在数据库删除应该是安全的
+6 -2
View File
@@ -1,7 +1,6 @@
package routers
import (
"fmt"
"saas/models"
"time"
@@ -28,6 +27,7 @@ func Fitst_use(ctx *gin.Context) {
}
}
var data_t map[string]interface{}
if err = mapstructure.Decode(jsonData["data"], &data_t); err == nil {
ctx.Set("data", &data_t)
@@ -80,7 +80,7 @@ func Fitst_use(ctx *gin.Context) {
models.DB.Create(&user_info) // 传入指针
}
//写入当前登录的用户信息 传递给下一个组件
fmt.Println(user_info)
//fmt.Println(user_info)
ctx.Set("user_info", &user_info)
ctx.Set("user", &user)
} else {
@@ -116,3 +116,7 @@ func Fitst_use(ctx *gin.Context) {
}
}
func Use_is_login(ctx *gin.Context) {
}
+55 -12
View File
@@ -27,23 +27,24 @@ function load_json(key) {
}
}
function post_json(path, json, callback) {
var host = "";
var port = 0;
var head_path = "/api/v1";
//把cookie插入json
var data = {};
data["data"] = json;
function post_file(path, file, file_name, callback) {
var head_path = "/api/v1/file";
// 创建FormData对象
const formData = new FormData();
formData.append("file", file, file_name); // 'file' 是后端接收文件的字段名
//获取保存的cookie
var cookie = load_json("cookie");
if (cookie) {
data["cookie"] = cookie;
}
//console.log(cookie);
formData.append("cookie", JSON.stringify(cookie)); //插入cookie
var re_data = {};
// 发送请求
axios
.post(head_path + path, data, {
.post(head_path + path, formData, {
headers: {
"Content-Type": "application/json",
"Content-Type": "multipart/form-data", // 这里实际上可以省略,因为FormData会被正确识别
},
})
.then((response) => {
@@ -69,3 +70,45 @@ function post_json(path, json, callback) {
callback(re_data);
});
}
function post_json(path, json, callback) {
var head_path = "/api/v1";
//把cookie插入json
var data = {};
data["data"] = json;
var cookie = load_json("cookie");
if (cookie) {
data["cookie"] = cookie;
}
var re_data = {};
axios
.post(head_path + path, data, {
headers: {
"Content-Type": "application/json",
},
})
.then((response) => {
//console.log(response)
re_data["statusCode"] = response.status;
//载入服务器返回的数据
if (response.data) {
re_data["data"] = response.data;
//自动保存服务器发送的cookie
if (response.data.cookie) {
if (response.data.cookie.Value == "") {
dele("cookie");
} else {
save_json("cookie", response.data.cookie);
}
}
}
callback(re_data);
})
.catch((error) => {
re_data["statusCode"] = -1;
re_data["error"] = error;
callback(re_data);
});
}
+58 -54
View File
@@ -83,12 +83,14 @@
<div class="row g-3">
<div class="col-md">
<div class="form-label">名字</div>
<input id="username" type="text" class="form-control" value="{{.user_info.Username}}" maxlength="30">
<input id="username" type="text" class="form-control" value="{{.user_info.Username}}"
maxlength="30">
</div>
<div class="col-md">
<div class="form-label">备注</div>
<input id="first_name" type="text" class="form-control" value="{{.user_info.FirstName}}" maxlength="50">
<input id="first_name" type="text" class="form-control" value="{{.user_info.FirstName}}"
maxlength="50">
</div>
</div>
@@ -230,9 +232,12 @@
/* 头像裁剪器样式*/
.container {
width: 95%; /* 改为百分比宽度 */
margin: 20px auto; /* 增加上下边距 */
max-width: 1200px; /* 保留最大宽度 */
width: 95%;
/* 改为百分比宽度 */
margin: 20px auto;
/* 增加上下边距 */
max-width: 1200px;
/* 保留最大宽度 */
background: white;
padding: 30px;
border-radius: 12px;
@@ -243,58 +248,76 @@
display: flex;
gap: 30px;
margin-top: 20px;
flex-wrap: wrap; /* 添加换行支持 */
flex-wrap: wrap;
/* 添加换行支持 */
}
/* 裁剪区域 */
.crop-section {
flex: 1 1 60%; /* 弹性布局基础宽度 */
min-width: 300px; /* 降低最小宽度 */
height: auto; /* 移除固定高度 */
min-height: 400px; /* 设置最小度 */
flex: 1 1 60%;
/* 弹性布局基础宽度 */
min-width: 300px;
/* 降低最小度 */
height: auto;
/* 移除固定高度 */
min-height: 400px;
/* 设置最小高度 */
}
#image-wrapper {
width: 100%;
height: 60vh; /* 改用视窗单位 */
max-height: 600px; /* 设置最大高度 */
height: 60vh;
/* 改用视窗单位 */
max-height: 600px;
/* 设置最大高度 */
background: #f8f9fa;
border: 2px dashed #ddd;
border-radius: 8px;
overflow: hidden;
}
/* 预览区域自适应 */
.preview-section {
flex: 1 1 35%; /* 弹性布局基础宽度 */
min-width: 250px; /* 设置合理最小宽度 */
flex: 1 1 35%;
/* 弹性布局基础宽度 */
min-width: 250px;
/* 设置合理最小宽度 */
}
/* 移动端适配 */
@media (max-width: 768px) {
.container {
padding: 15px; /* 减少内边距 */
padding: 15px;
/* 减少内边距 */
}
.flex-wrapper {
flex-direction: column; /* 垂直排列 */
flex-direction: column;
/* 垂直排列 */
}
.crop-section,
.preview-section {
width: 100% !important; /* 强制全宽 */
min-width: unset; /* 移除最小宽度 */
width: 100% !important;
/* 强制全宽 */
min-width: unset;
/* 移除最小宽度 */
}
#image-wrapper {
height: 50vh; /* 调整移动端高度 */
height: 50vh;
/* 调整移动端高度 */
}
.preview-box {
width: 120px; /* 缩小预览区域 */
width: 120px;
/* 缩小预览区域 */
height: 120px;
}
.controls {
flex-direction: column; /* 垂直排列按钮 */
flex-direction: column;
/* 垂直排列按钮 */
margin-top: 10px;
}
}
@@ -519,7 +542,7 @@
const progressBar = document.querySelector('.progress-bar');
const progressContainer = document.querySelector('.progress-container');
try {
if (!cropper) {
showMessage('⚠️ 请先选择并裁剪图片', 'error');
return;
@@ -536,42 +559,23 @@
canvas.toBlob(resolve, 'image/jpeg', 0.9)
);
const formData = new FormData();
formData.append('file', blob, `avatar_${Date.now()}.jpg`);
formData.append('meta', JSON.stringify({
width: canvas.width,
height: canvas.height,
scale: currentScale.toFixed(2)
}));
const response = await fetch('/api/v1/file/avatar', {
method: 'POST',
body: formData,
headers: {
'X-Requested-With': 'XMLHttpRequest'
}
});
if (!response.ok) throw new Error(`服务器错误: ${response.status}`);
const result = await response.json();
if (result.err_code == 0) {
showMessage(`✅ 上传成功!`, 'success');
set_user_avatar(result.data.path);
console.log(get_user_avatar());
avatar_toolt.hide();
post_file("/upload", blob, `avatar_${Date.now()}.jpg`, (c) => {
if (c.statusCode == 200) {
if (c.data.err_code == 0) {
//save_json("cookie", c.data.return.cookie)
banner_alert('success', "更换成功", 950)
} else {
showMessage(`❌ 上传失败: ${result.err_msg}`, 'error');
banner_alert('warning', "服务错误", 3000)
}
} else {
banner_alert('danger', "网络连接错误:" + c.statusCode, 3000)
}
})
} catch (error) {
console.error('上传错误:', error);
showMessage(`❌ 上传失败: ${error.message}`, 'error');
} finally {
progressBar.style.width = '0%';
progressContainer.style.display = 'none';
}
});
// 消息提示