613 字
3 分钟
文件处理
上传单个文件
r.POST("/upload", func(c *gin.Context) {
// 获取上传文件 file, err := c.FormFile("file") if err != nil { c.JSON(400, gin.H{ "error": err.Error(), }) return }
// 创建上传目录 err := os.MkdirAll("./upload", os.ModePerm) if err != nil { panic(err) }
// 自定义文件名 filename := fmt.Sprintf( "%d%s", time.Now().UnixNano(), filepath.Ext(file.Filename), )
// 将上传文件保存到指定路径 err = c.SaveUploadedFile(file, "./upload/"+file.Filename) if err != nil { c.JSON(500, gin.H{ "error": err.Error(), }) return }
c.JSON(200, gin.H{ "filename": file.Filename, })})上传多个文件
r.POST("/uploads", func(c *gin.Context) {
// 一次上传多个文件 form, err := c.MultipartForm() if err != nil { c.JSON(400, gin.H{ "error": err.Error(), }) return }
files := form.File["files"]
for _, file := range files { c.SaveUploadedFile(file, "./upload/"+file.Filename) }
c.JSON(200, gin.H{ "count": len(files), })})获取上传文件信息
r.POST("/info", func(c *gin.Context) {
// 获取文件名、大小、请求头等信息 file, err := c.FormFile("file") if err != nil { return }
// 获取上传文件后缀 ext := filepath.Ext(file.Filename) fmt.Println(ext)
c.JSON(200, gin.H{ "filename": file.Filename, "size": file.Size, "header": file.Header, })})读取上传文件内容
r.POST("/read", func(c *gin.Context) {
// 读取文件内容,而不直接保存 fileHeader, _ := c.FormFile("file")
file, _ := fileHeader.Open() defer file.Close()
data, _ := io.ReadAll(file)
c.JSON(200, gin.H{ "content": string(data), })})判断文件类型
r.POST("/judgeType", func(c *gin.Context) {
fileHeader, _ := c.FormFile("file")
file, _ := fileHeader.Open() defer file.Close()
buffer := make([]byte, 512)
file.Read(buffer)
// 检测文件真实 MIME 类型 contentType := http.DetectContentType(buffer)
fmt.Println(contentType)})限制上传大小
r := gin.Default()
// 最大 8MBr.MaxMultipartMemory = 8 << 20
// 或者业务判断r.POST("/judgeSize", func(c *gin.Context) {
file, _ := c.FormFile("file")
if file.Size > 5*1024*1024 { c.JSON(400, gin.H{ "error": "文件超过5MB", }) return }})下载本地文件
r.GET("/download", func(c *gin.Context) {
// 返回服务器本地文件 c.File("./upload/test.pdf")
})强制下载文件
r.GET("/download", func(c *gin.Context) {
// 浏览器弹出下载,而不是预览 c.FileAttachment( "./upload/test.pdf", "test.pdf", )
})返回字节流
r.GET("/data", func(c *gin.Context) {
// 返回内存中的二进制数据 data := []byte("Hello Gin")
c.Data( 200, "text/plain", data, )
})下载 JSON 文件
r.GET("/json", func(c *gin.Context) {
// 动态生成 JSON 文件下载 user := map[string]any{ "name": "Tom", "age": 18, }
data, _ := json.Marshal(user)
c.Header( "Content-Disposition", "attachment; filename=user.json", )
c.Data( 200, "application/json", data, )
})自定义响应 Header 下载
r.GET("/download", func(c *gin.Context) {
c.Header( "Content-Disposition", "attachment; filename=test.pdf", )
c.File("./upload/test.pdf")
})流式下载大文件
r.GET("/stream", func(c *gin.Context) {
// 避免一次性读入内存,适合视频、压缩包等大文件 file, err := os.Open("./movie.mp4") if err != nil { c.Status(404) return } defer file.Close()
io.Copy(c.Writer, file)
})暴露静态资源目录
r := gin.Default()
// 将整个目录作为静态资源目录r.Static("/static", "./static")暴露单个静态文件
r := gin.Default()
// 只暴露一个文件r.StaticFile( "/favicon.ico", "./favicon.ico",)返回 HTML 文件
r := gin.Default()
// 直接返回指定 HTML 页面r.StaticFile( "/index", "./index.html",)分享文章
生成精美分享图或复制链接,与更多人分享本文。
继续阅读
换条路线
从其他文章中稳定抽取
最后更新于 ,距今已过 89 天
部分内容可能已过时