Go Gin 实现文件的上传下载流读取
文件上传

  • router
router.POST("/resources/common/upload",  service.UploadResource)

  • service
    type: POST

    data:{

    ​ “saveDir”:“保存的路径”,

    ​ “fileName”:“文件名称不带后缀”

    ​ }
// 上传文件
func UploadResource(c *gin.Context) {
  saveDirParam := c.PostForm("saveDir")   // 文件目录
  fileNameParam := c.PostForm("fileName") // 文件名称
  //目录
  var saveDir = ""
  //名称
  var saveName = ""
  //完整路径
  var savePath = ""
  //获取文件
  file, header, errFile := c.Request.FormFile("file")
  //处理获取文件错误
  if errFile != nil || common.IsEmpty(header.Filename) {
      c.JSON(http.StatusOK, gin.H{
          "success": false,
          "message": "请选择文件",
          "dir":     saveDir,
          "name":    saveName,
          "path":    savePath,
      })
      return
  }
  //目录请求参数为空
  if common.IsEmpty(saveDirParam) {
      c.JSON(http.StatusOK, gin.H{
          "success": false,
          "message": "请求参数错误!",
          "dir":     saveDir,
          "name":    saveName,
          "path":    savePath,
      })
      return
  }
  //如果上传的名称为空,则自动生成名称
  if common.IsEmpty(fileNameParam) {
      fileNameParam = GenerateResourceNo()
  }
  //获取上传文件的后缀(类型)
  uploadFileNameWithSuffix := path.Base(header.Filename)
  uploadFileType := path.Ext(uploadFileNameWithSuffix)
  //文件保存目录
  saveDir = "/attachment" + saveDirParam
  //保存的文件名称
  saveName = fileNameParam + uploadFileType
  savePath = saveDir + "/" + saveName
  //打开目录
  localFileInfo, fileStatErr := os.Stat(saveDir)
  //目录不存在
  if fileStatErr != nil || !localFileInfo.IsDir() {
      //创建目录
      errByMkdirAllDir := os.MkdirAll(saveDir, 0755)
      if errByMkdirAllDir != nil {
          logs.Error("%s mkdir error.....", saveDir, errByMkdirAllDir.Error())
          c.JSON(http.StatusOK, gin.H{
              "success": false,
              "dir":     saveDir,
              "name":    saveName,
              "path":    savePath,
              "message": "创建目录失败",
          })
          return
      }
  }
  ////上传文件前 先删除该资源之前上传过的资源文件
  ////(编辑-重新选择文件-需要先删除该资源之前上传过的资源文件)
    ////该代码执行的条件----上传的名称是唯一的,否则会出现误删
  ////获取文件的前缀
  //fileNameOnly := fileNameParam
  //deleteFileWithName(fileNameOnly, saveDir)
  //deleteFileWithName(fileNameOnly, model.WebConfig.ResourcePath+"/"+
  //  model.WebConfig.WebConvertToPath)

  out, err := os.Create(savePath)
  if err != nil {
      logs.Error(err)
  }
  defer out.Close()
  _, err = io.Copy(out, file)
  if err != nil {
      c.JSON(http.StatusOK, gin.H{
          "success": false,
          "dir":     saveDir,
          "name":    saveName,
          "path":    savePath,
          "message": err.Error(),
      })
      return
  }

  //没有错误的情况下
  c.JSON(http.StatusOK, gin.H{
      "success": true,
      "dir":     saveDir,
      "name":    saveName,
      "path":    savePath,
      "message": "上传成功",
  })
  return
}
js提交例子:

注:需导入jquery.js 和 ajaxfileupload.js
//上传文件
        $.ajaxFileUpload(
            {
                url: '/resources/common/upload', //用于文件上传的服务器端请求地址
                secureuri: false, //是否需要安全协议,一般设置为false
                fileElementId: fileUploadDomId, //文件上传域的ID
                data: {
                    "saveDir":fileSaveDir,
                    "fileName":fileSaveName
                },
                dataType: 'json', //返回值类型 一般设置为json
                contentType:'application/json',//提交的数据类型
                async: false,
                success: function (data, status)  //服务器成功响应处理函数
                {
                    if (data.success){
                        fileSaveName=fileSaveDir+"/"+data.name;
                        console.log("上传成功,返回的文件的路径:",fileSaveName)
                    }else{
                        console.log("上传失败,返回的文件的路径:",fileSaveName)
                        return
                    }
                },
                error: function (data, status, e)//服务器响应失败处理函数
                {
                    console.log("e==",e);
                    return
                }
            }
        );

文件的下载

  • router
    Type:‘GET’

普通链接格式非restful风格

参数url:下载的文件的路径

​ Jquery解码:decodeURIComponent(url);

​ Jquery编码:encodeURIComponent(url);

例:http://127.0.0.0.1:8080//pub/common/download?url=“/attachment/demo.docx”

router.GET("/pub/common/download", service.PubResFileStreamGetService)

  • service
//下载次数
func UserFileDownloadCommonService(c *gin.Context) {
    filePath := c.Query("url")
  //打开文件
  fileTmp, errByOpenFile := os.Open(filePath)
  defer fileTmp.Close()
    
    //获取文件的名称
    fileName:=path.Base(filePath)
  c.Header("Content-Type", "application/octet-stream")
  c.Header("Content-Disposition", "attachment; filename="+fileName)
  c.Header("Content-Transfer-Encoding", "binary")
  c.Header("Cache-Control", "no-cache")
  if common.IsEmpty(filePath) || common.IsEmpty(fileName) || errByOpenFile != nil {
        logs.Error("获取文件失败")
      c.Redirect(http.StatusFound, "/404")
      return
  } 
  c.Header("Content-Type", "application/octet-stream")
      c.Header("Content-Disposition", "attachment; filename="+fileName)
      c.Header("Content-Transfer-Encoding", "binary")

  c.File(filePath)
    return

}

文件流读取

  • router
    Type:‘GET’

普通链接格式非restful风格

参数url:下载的文件的路径

​ Jquery解码:decodeURIComponent(url);

​ Jquery编码:encodeURIComponent(url);

例:http://127.0.0.0.1:8080//pub/common/file_stream?url=“/attachment/demo.docx”

router.GET("/pub/common/file_stream", service.PubResFileStreamGetService)

  • service
//map for  Http Content-Type  Http 文件类型对应的content-Type
var HttpContentType = map[string]string{
  ".avi": "video/avi",
  ".mp3": "   audio/mp3",
  ".mp4": "video/mp4",
  ".wmv": "   video/x-ms-wmv",
  ".asf":  "video/x-ms-asf",
  ".rm":   "application/vnd.rn-realmedia",
  ".rmvb": "application/vnd.rn-realmedia-vbr",
  ".mov":  "video/quicktime",
  ".m4v":  "video/mp4",
  ".flv":  "video/x-flv",
  ".jpg":  "image/jpeg",
  ".png":  "image/png",
}

//根据文件路径读取返回流文件 参数url
func PubResFileStreamGetService(c *gin.Context) {
filePath := c.Query("url")
//获取文件名称带后缀
fileNameWithSuffix := path.Base(filePath)
//获取文件的后缀
fileType := path.Ext(fileNameWithSuffix)
//获取文件类型对应的http ContentType 类型
fileContentType := HttpContentType[fileType]
if common.IsEmpty(fileContentType) {
  c.String(http.StatusNotFound, "file http contentType not found")
  return
}
c.Header("Content-Type", fileContentType)
c.File(filePath)
}