This commit is contained in:
2026-06-30 13:08:18 +07:00
parent 795726aea5
commit 1c2bfde005
18 changed files with 1504 additions and 90 deletions

View File

@@ -919,12 +919,13 @@ func GetStudentExamPaperFilesHandler(db *gorm.DB) fiber.Handler {
resList = append(resList, fiber.Map{
"id": r.ID,
"fileName": r.FileName,
"url": fmt.Sprintf("/api/student/exam/download?studentRkId=%d&kind=resource&fileId=%d", studentID, r.ID),
"url": fmt.Sprintf("/api/student/exam/download?studentRkId=%d&kind=resource&fileId=%d&view=1", studentID, r.ID),
"downloadUrl": fmt.Sprintf("/api/student/exam/download?studentRkId=%d&kind=resource&fileId=%d", studentID, r.ID),
})
}
return c.JSON(fiber.Map{
"paperTitle": info.Paper.Title,
"pdfUrl": fmt.Sprintf("/api/student/exam/download?studentRkId=%d&kind=pdf", studentID),
"pdfUrl": fmt.Sprintf("/api/student/exam/download?studentRkId=%d&kind=pdf&view=1", studentID),
"resources": resList,
})
}
@@ -941,19 +942,61 @@ func DownloadStudentExamFileHandler(db *gorm.DB) fiber.Handler {
if info == nil || info.Enrollment.PaperSentAt == nil || info.Paper == nil {
return c.Status(403).JSON(fiber.Map{"error": "Không có quyền"})
}
inline := c.Query("view") == "1" || c.Query("inline") == "1"
kind := c.Query("kind", "pdf")
if kind == "pdf" {
return c.Download(info.Paper.PdfPath, filepath.Base(info.Paper.PdfPath))
name := filepath.Base(info.Paper.PdfPath)
if inline {
return sendExamFileInline(c, info.Paper.PdfPath, name)
}
return c.Download(info.Paper.PdfPath, name)
}
fileID, _ := strconv.ParseUint(c.Query("fileId", "0"), 10, 64)
var res models.ExamPaperResource
if err := db.Where("id = ? AND exam_paper_id = ?", fileID, info.Paper.ID).First(&res).Error; err != nil {
return c.Status(404).JSON(fiber.Map{"error": "File không tồn tại"})
}
if inline && examFileCanViewInline(res.FileName) {
return sendExamFileInline(c, res.FilePath, res.FileName)
}
return c.Download(res.FilePath, res.FileName)
}
}
func examFileCanViewInline(fileName string) bool {
switch strings.ToLower(filepath.Ext(fileName)) {
case ".pdf", ".png", ".jpg", ".jpeg", ".gif", ".webp", ".txt":
return true
default:
return false
}
}
func examViewMimeType(fileName string) string {
switch strings.ToLower(filepath.Ext(fileName)) {
case ".pdf":
return "application/pdf"
case ".png":
return "image/png"
case ".jpg", ".jpeg":
return "image/jpeg"
case ".gif":
return "image/gif"
case ".webp":
return "image/webp"
case ".txt":
return "text/plain; charset=utf-8"
default:
return "application/octet-stream"
}
}
func sendExamFileInline(c *fiber.Ctx, filePath, fileName string) error {
c.Set("Content-Type", examViewMimeType(fileName))
c.Set("Content-Disposition", fmt.Sprintf("inline; filename=%q", fileName))
return c.SendFile(filePath)
}
// POST /api/student/exam/submit — multipart zip
func SubmitStudentExamHandler(db *gorm.DB) fiber.Handler {
return func(c *fiber.Ctx) error {