前言:
目前看官们对“用c语言编写图案”大概比较讲究,你们都需要分析一些“用c语言编写图案”的相关知识。那么小编也在网摘上搜集了一些对于“用c语言编写图案””的相关文章,希望兄弟们能喜欢,兄弟们一起来学习一下吧!无论是博客还是其它类型的富文本平台,发布文章或想法怎么能少的了图片吗?这一节咱们就完成图片上传部分的编写。
先把Article模型修改一下:
package modelsimport ( "gorm.io/gorm")type Article struct { gorm.Model Title string `gorm:"type:varchar(255);not null" json:"title" form:"title"` Content string `gorm:"type:text;not null" json:"content" form:"content"` UserID uint `gorm:"not null" json:"user_id"` User User `gorm:"foreignKey:UserID"` CoverImage string `gorm:"type:varchar(255)" json:"cover_image"` Images []Image `gorm:"foreignKey:ArticleID"`}type Image struct { gorm.Model URL string `gorm:"type:varchar(255);not null" json:"url"` ArticleID uint `gorm:"not null" json:"article_id"`}
我给Title和Content添加了form标签,拿form:"title"来解释。它是一个结构体标签(struct tag),它在 Go 语言中用于为结构体的字段添加元数据。当你在 Go 中处理 HTTP 请求时,经常需要从请求体或查询参数中解析数据。这些数据通常会被解析到一个结构体中。form 标签就是在这个解析过程中起作用的。具体来说,form:"title" 意味着当你从一个表单请求(如 POST 或 PUT 请求的内容类型为 application/x-www-form-urlencoded 或 multipart/form-data)中解析数据到这个结构体时,Go 将会查找表单数据中名为 title 的字段,并将其值解析到结构体的对应字段中。
CoverImage 代表文章的封面图片,它用于存储图片的路径。
Image是新添加的结构体,我们用它保存文章中的图片路径。它与Article结构体是多对一的关系。
接着在db.go文件中把Image数据库迁移加上,请看如下代码:
err = db.AutoMigrate(&User{}, &Article{}, &Image{})
完成上述代码后,我们需要去实现上传图片部分的代码编写。这部分有修改也有新增。完成代码如下:
package apiimport ( "log" "net/http" "path/filepath" "xblog/models" "github.com/gin-gonic/gin")// CreateArticle 创建新文章func CreateArticle(c *gin.Context) { // 从上下文中获取当前用户 currentUser, _ := c.Get("currentUser") user, ok := currentUser.(*models.JwtClaims) if !ok { c.JSON(http.StatusUnauthorized, gin.H{"error": "无法获取用户认证信息"}) return } // 获取上传的封面图片 coverImage, err := c.FormFile("cover_image") if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "无法获取封面图片"}) return } // 获取文章内容中的图片 contentImages, err := c.MultipartForm() if err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": "无法获取图片"}) return } // 初始化Article结构体 var article models.Article // 绑定请求体到article结构体 if err := c.ShouldBind(&article); err != nil { c.JSON(http.StatusBadRequest, gin.H{"error": err.Error()}) return } // 设置文章的UserID为当前用户的ID article.UserID = user.UserID // 保存封面图片到文件系统并将路径保存至数据库 coverImagePath := filepath.Join("/home/nonm/codes/xblog/static/cover/images", coverImage.Filename) if err := c.SaveUploadedFile(coverImage, coverImagePath); err != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "保存封面图片失败"}) return } article.CoverImage = coverImagePath // 保存文章到数据库 if result := models.DB.Create(&article); result.Error != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error()}) return } // 保存文章内容中的图片到文件系统并将路径保存至数据库 for _, contentImage := range contentImages.File["content_images"] { contentImagePath := filepath.Join("/home/nonm/codes/xblog/static/content/images", contentImage.Filename) log.Printf("Saving content image: %s\n", contentImagePath) if err := c.SaveUploadedFile(contentImage, contentImagePath); err != nil { log.Printf("Failed to save content image: %s, error: %v\n", contentImagePath, err) c.JSON(http.StatusInternalServerError, gin.H{"error": "保存文章内图片失败"}) return } image := models.Image{ URL: contentImagePath, ArticleID: article.ID, } if result := models.DB.Create(&image); result.Error != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": result.Error.Error()}) return } } // 预加载User和Images数据 if result := models.DB.Preload("User").Preload("Images").First(&article, article.ID); result.Error != nil { c.JSON(http.StatusInternalServerError, gin.H{"error": "加载文章详情时出现错误"}) return } // 返回创建的文章 c.JSON(http.StatusOK, gin.H{"article": article})}
可以看到我先是添加了获取上传封面图片(CoverImage)与获取文章内容中的图片(ContentImages)这两个语句块。
这里重点解释一下保存封面图片到文件系统并将路径保存至数据库。
coverImagePath := filepath.Join("/home/nonm/codes/xblog/static/cover/images", coverImage.Filename) 这行代码使用 filepath.Join 函数来构造封面图片的保存路径。filepath.Join 是一个用于连接文件路径的函数,它会根据操作系统使用正确的路径分隔符。它连接了两个字符串:"/home/nonm/codes/xblog/static/cover/images"(这是服务器上用于存储封面图片的目录路径)和 coverImage.Filename(上传文件的原始文件名)以创建出一个完整的文件路径。当然您也可以使用相对路径。
if err := c.SaveUploadedFile(coverImage, coverImagePath); err != nil { 接下来,使用 Gin 的 c.SaveUploadedFile 函数尝试将上传的封面图片文件保存到上一步构造的文件路径。c.SaveUploadedFile 接受两个参数:上传的文件 (coverImage) 和目标保存路径 (coverImagePath)。如果保存文件过程中出现任何错误,SaveUploadedFile 函数会返回一个错误 (err)。如果 err 不为 nil,这意味着保存文件时发生了错误。在这种情况下,代码会使用 c.JSON 方法向客户端返回一个状态码为 500 Internal Server Error 的 HTTP 响应,并附上一个包含错误信息 "保存封面图片失败" 的 JSON 对象。
如果没有错误发生,文件成功保存到服务器,那么 coverImagePath(包含了新保存的封面图片的完整路径)将被赋值给 article.CoverImage。这样,文章的 CoverImage 字段就包含了指向封面图片文件的路径,可以在后续过程中用于引用或显示封面图片。
for _, contentImage := range contentImages.File["content_images"] { 这行代码遍历 contentImages.File["content_images"] 切片,这个切片包含了所有上传的文章内容图片。这是一个 for 循环,contentImage 是循环变量,代表当前遍历到的图片。
contentImagePath := filepath.Join("/home/nonm/codes/xblog/static/content/images", contentImage.Filename) 这行代码和前面的 coverImagePath 作用一样。
log.Printf("Saving content image: %s\n", contentImagePath) 这行代码使用 log.Printf 打印日志,记录正在保存的图片路径。对于跟踪和调试非常有用。
if err := c.SaveUploadedFile(contentImage, contentImagePath); err != nil { 使用 Gin 的 c.SaveUploadedFile 函数尝试将当前遍历到的文章内容图片文件保存到指定路径。如果保存文件过程出错,函数会返回一个错误 (err)。如果保存文件出错,打印失败的日志,并使用 c.JSON 向客户端返回一个状态码为 500 Internal Server Error 的 HTTP 响应,附上错误信息 "保存文章内图片失败"。
如果文件成功保存,将创建一个新的 models.Image 实例(image),设置 URL 字段为图片的保存路径(contentImagePath),设置 ArticleID 字段为当前文章的 ID。
if result := models.DB.Create(&image); result.Error != nil { 使用 GORM 的 Create 方法尝试将 Image 实例保存到数据库。如果保存过程出错,函数会返回一个包含错误信息的 result.Error,并向客户端返回一个状态码为 500 Internal Server Error 的 HTTP 响应,并附上错误信息。
关于预加载请看上一篇文件。这里就不再次解释了。
好,到这里我们图片上传代码就编写完成了。使用Curl去测试一下。
如图可知,文件系统与数据库都成功保存了相应的数据。
标签: #用c语言编写图案