上传图片处理

服务端处理:

package main

import (
   "encoding/json"
   "fmt"
   "html/template"
   "io"
   "math/rand"
   "mime/multipart"
   "net/http"
   "os"
   "path"
   "path/filepath"
   "sort"
   "strings"
   "time"
)

func GetJSON(errcode int, errmsg string, data interface{}) string {
   var slice = make(map[string]interface{})
   slice["errcode"] = errcode
   slice["errmsg"] = errmsg
   slice["data"] = data

   jsonByte, _ := json.Marshal(slice)
   return string(jsonByte)
}

func InSlice(needle string, slice []string) bool {
   sort.Strings(slice)
   index := sort.SearchStrings(slice, needle)
   if index < len(slice) && slice[index] == needle {
      return true
   }

   return false
}

func RandString(length int) string {
   letters := "0123456789abcdefghijklmnopqrstuvwxyz"

   bytes := []byte(letters)
   var randString []byte
   random := rand.New(rand.NewSource(time.Now().UnixNano()))
   for i := 0; i < length; i++ {
      randString = append(randString, bytes[random.Intn(len(bytes))])
   }

   return string(randString)
}

func main() {
   http.HandleFunc("/demo", func(writer http.ResponseWriter, request *http.Request) {
      if request.Method == "POST" {
         //========== 获取POST参数 ==========//
         name := request.FormValue("name")     // 获取name参数
         age := request.FormValue("age")       // 获取age参数
         gender := request.FormValue("gender") // 获取gender参数

         var data = make(map[string]interface{}) // 前端接收该值时是一个对象

         if name == "" {
            writer.Header().Set("Content-Type", "application/json; charset=utf-8")
            _, _ = io.WriteString(writer, GetJSON(1, "请输入姓名", data))
            // {"data":{},"errcode":1,"errmsg":"请输入姓名"}
            return
         }

         if age == "" {
            writer.Header().Set("Content-Type", "application/json; charset=utf-8")
            _, _ = io.WriteString(writer, GetJSON(1, "请输入年龄", data))
            // {"data":{},"errcode":1,"errmsg":"请输入年龄"}
            return
         }

         if gender == "" {
            writer.Header().Set("Content-Type", "application/json; charset=utf-8")
            _, _ = io.WriteString(writer, GetJSON(1, "请输入性别", data))
            // {"data":{},"errcode":1,"errmsg":"请输入性别"}
            return
         }

         //========== 处理上传图片 ==========//
         _ = request.ParseMultipartForm(32 << 20) // 设置内存大小

         // 检查是否上传了头像图片
         uploadFile, uploadFileHeader, err := request.FormFile("head") // FormFile()的参数是<input name="head" type="file">里的name属性值
         if err != nil {
            writer.Header().Set("Content-Type", "application/json; charset=utf-8")
            _, _ = io.WriteString(writer, GetJSON(1, "请选择头像图片", data))
            return
         }

         defer func(uploadFile multipart.File) {
            err := uploadFile.Close()
            if err != nil {
               // TODO...
            }
         }(uploadFile)

         // 图片源文件信息
         fmt.Printf("图片源文件大小:%+v字节 \n", uploadFileHeader.Size)
         fmt.Printf("图片源文件名称:%+v \n", uploadFileHeader.Filename)
         fmt.Printf("图片源文件头信息:%+v \n", uploadFileHeader.Header)

         // 检查图片格式是否合法
         var allowContentType = []string{"image/jpeg", "image/png", "image/gif"}
         contentType := strings.Join(uploadFileHeader.Header.Values("Content-Type"), "") // []string转string
         if !InSlice(contentType, allowContentType) {
            writer.Header().Set("Content-Type", "application/json; charset=utf-8")
            _, _ = io.WriteString(writer, GetJSON(1, "图片格式不合法", data))
            return
         }

         // 检查图片大小是否超过最大限制
         maxSize := int64(1048576 * 2) // 提示:1MB = 1048576字节
         if uploadFileHeader.Size > maxSize {
            writer.Header().Set("Content-Type", "application/json; charset=utf-8")
            _, _ = io.WriteString(writer, GetJSON(1, "图片大小超过限制", data))
            return
         }

         // 构造文件保存路径
         location, _ := time.LoadLocation("Asia/Shanghai")
         rootPath, _ := os.Getwd()
         ext := filepath.Ext(uploadFileHeader.Filename) // 获取文件扩展名,含小数点,如:.jpg
         saveFilepath := rootPath + "/upload/" + time.Now().In(location).Format("200601/02/") + RandString(32) + ext
         _ = os.MkdirAll(path.Dir(saveFilepath), 0755) // 创建保存目录

         // 保存图片,使用os.OpenFile()或os.Create()均可
         // saveFile, err := os.OpenFile(saveFilepath, os.O_WRONLY|os.O_CREATE, 0644)
         saveFile, err := os.Create(saveFilepath)
         if err != nil {
            writer.Header().Set("Content-Type", "application/json; charset=utf-8")
            _, _ = io.WriteString(writer, GetJSON(1, "上传图片失败,原因:无法创建图片", data))
            return
         }

         defer func(saveFile *os.File) {
            err := saveFile.Close()
            if err != nil {
               // TODO...
            }
         }(saveFile)

         _, err = io.Copy(saveFile, uploadFile)
         if err != nil {
            writer.Header().Set("Content-Type", "application/json; charset=utf-8")
            _, _ = io.WriteString(writer, GetJSON(1, "上传图片失败,原因:无法保存图片", data))
            return
         }

         // 所有操作完成,返回操作成功信息
         data["uid"] = 9527
         writer.Header().Set("Content-Type", "application/json; charset=utf-8")
         _, _ = io.WriteString(writer, GetJSON(0, "", data)) // {"data":{"uid":9527},"errcode":0,"errmsg":""}
      } else {
         rootPath, _ := os.Getwd()
         tplFilePath := rootPath + "/template/default/demo.htm" // 模板文件硬盘路径

         // 解析模板文件
         tpl, err := template.ParseFiles(tplFilePath)
         if err != nil {
            panic("解析模板文件出错,原因:" + err.Error())
         }

         // 需要在模板显示的数据
         data := map[string]interface{}{
            "title": "上传图片处理 - 码农人生", // 模板文件调用示例:{{.title}}
         }

         // 渲染模板文件
         err = tpl.Execute(writer, data)
         if err != nil {
            panic("渲染模板文件出错,原因:" + err.Error())
         }
      }
   })

   _ = http.ListenAndServe(":8081", nil)
}



HTML页面:

<!doctype html>
<html lang="zh">
<head>
  <meta charset="utf-8">
  <title>{{.title}}</title>
</head>
<body>
<form id="form">
  <input name="name" type="text" placeholder="请输入姓名" value="张三">
  <br>
  <br>
  <input name="age" type="text" placeholder="请输入年龄" value="18">
  <br>
  <br>
  <input name="gender" type="text" placeholder="请输入性别" value="男">
  <br>
  <br>
  <input name="head" type="file">
  <br>
  <br>
  <button type="button" action="submit" disabled>提交</button>
</form>
<script type="text/javascript" src="https://code.jquery.com/jquery-1.12.4.min.js"></script>
<script type="text/javascript">
  $(function() {
    $('button[action="submit"]').click(function() {
      $.ajax({
        dataType: 'json',
        type: 'POST',
        processData: false,
        contentType: false,
        data: new FormData($('#form')[0]),
        success: function(response) {
          if (response.errcode == 0) {
            alert('提交成功')
          } else {
            alert(response.errmsg)
          }
        },
      })
    });
    $('button[action="submit"]').prop('disabled', false)
  });
</script>
</body>
</html>

Copyright © 2024 码农人生. All Rights Reserved