Go Gin 實(shí)現(xiàn)文件的上傳下載流讀取

Go Gin 實(shí)現(xiàn)文件的上傳下載流讀取

文件上傳

  • 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")
      //處理獲取文件錯(cuò)誤
      if errFile != nil || common.IsEmpty(header.Filename) {
          c.JSON(http.StatusOK, gin.H{
              "success": false,
              "message": "請(qǐng)選擇文件",
              "dir":     saveDir,
              "name":    saveName,
              "path":    savePath,
          })
          return
      }
      //目錄請(qǐng)求參數(shù)為空
      if common.IsEmpty(saveDirParam) {
          c.JSON(http.StatusOK, gin.H{
              "success": false,
              "message": "請(qǐng)求參數(shù)錯(cuò)誤钮追!",
              "dir":     saveDir,
              "name":    saveName,
              "path":    savePath,
          })
          return
      }
      //如果上傳的名稱為空训桶,則自動(dòng)生成名稱
      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() {
          //創(chuàng)建目錄
          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": "創(chuàng)建目錄失敗",
              })
              return
          }
      }
      ////上傳文件前 先刪除該資源之前上傳過的資源文件
      ////(編輯-重新選擇文件-需要先刪除該資源之前上傳過的資源文件)
        ////該代碼執(zhí)行的條件----上傳的名稱是唯一的樊零,否則會(huì)出現(xiàn)誤刪
      ////獲取文件的前綴
      //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
      }
    
      //沒有錯(cuò)誤的情況下
      c.JSON(http.StatusOK, gin.H{
          "success": true,
          "dir":     saveDir,
          "name":    saveName,
          "path":    savePath,
          "message": "上傳成功",
      })
      return
    }
    
    

    js提交例子:

    注:需導(dǎo)入jquery.js 和 ajaxfileupload.js

    //上傳文件
            $.ajaxFileUpload(
                {
                    url: '/resources/common/upload', //用于文件上傳的服務(wù)器端請(qǐng)求地址
                    secureuri: false, //是否需要安全協(xié)議,一般設(shè)置為false
                    fileElementId: fileUploadDomId, //文件上傳域的ID
                    data: {
                        "saveDir":fileSaveDir,
                        "fileName":fileSaveName
                    },
                    dataType: 'json', //返回值類型 一般設(shè)置為json
                    contentType:'application/json',//提交的數(shù)據(jù)類型
                    async: false,
                    success: function (data, status)  //服務(wù)器成功響應(yīng)處理函數(shù)
                    {
                        if (data.success){
                            fileSaveName=fileSaveDir+"/"+data.name;
                            console.log("上傳成功,返回的文件的路徑:",fileSaveName)
                        }else{
                            console.log("上傳失敗氓润,返回的文件的路徑:",fileSaveName)
                            return
                        }
                    },
                    error: function (data, status, e)//服務(wù)器響應(yīng)失敗處理函數(shù)
                    {
                        console.log("e==",e);
                        return
                    }
                }
            );
    

文件的下載

  • router

    Type:‘GET’

    普通鏈接格式非restful風(fēng)格

    參數(shù)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

    //下載次數(shù)
    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風(fēng)格

    參數(shù)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 文件類型對(duì)應(yīng)的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",
}

//根據(jù)文件路徑讀取返回流文件 參數(shù)url
func PubResFileStreamGetService(c *gin.Context) {
filePath := c.Query("url")
//獲取文件名稱帶后綴
fileNameWithSuffix := path.Base(filePath)
//獲取文件的后綴
fileType := path.Ext(fileNameWithSuffix)
//獲取文件類型對(duì)應(yīng)的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)
}
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
  • 序言:七十年代末,一起剝皮案震驚了整個(gè)濱河市薯鳍,隨后出現(xiàn)的幾起案子咖气,更是在濱河造成了極大的恐慌,老刑警劉巖挖滤,帶你破解...
    沈念sama閱讀 212,222評(píng)論 6 493
  • 序言:濱河連續(xù)發(fā)生了三起死亡事件崩溪,死亡現(xiàn)場(chǎng)離奇詭異,居然都是意外死亡斩松,警方通過查閱死者的電腦和手機(jī)伶唯,發(fā)現(xiàn)死者居然都...
    沈念sama閱讀 90,455評(píng)論 3 385
  • 文/潘曉璐 我一進(jìn)店門,熙熙樓的掌柜王于貴愁眉苦臉地迎上來惧盹,“玉大人乳幸,你說我怎么就攤上這事【” “怎么了粹断?”我有些...
    開封第一講書人閱讀 157,720評(píng)論 0 348
  • 文/不壞的土叔 我叫張陵,是天一觀的道長(zhǎng)嫡霞。 經(jīng)常有香客問我瓶埋,道長(zhǎng),這世上最難降的妖魔是什么诊沪? 我笑而不...
    開封第一講書人閱讀 56,568評(píng)論 1 284
  • 正文 為了忘掉前任养筒,我火速辦了婚禮,結(jié)果婚禮上娄徊,老公的妹妹穿的比我還像新娘闽颇。我一直安慰自己,他們只是感情好寄锐,可當(dāng)我...
    茶點(diǎn)故事閱讀 65,696評(píng)論 6 386
  • 文/花漫 我一把揭開白布。 她就那樣靜靜地躺著尖啡,像睡著了一般橄仆。 火紅的嫁衣襯著肌膚如雪。 梳的紋絲不亂的頭發(fā)上衅斩,一...
    開封第一講書人閱讀 49,879評(píng)論 1 290
  • 那天盆顾,我揣著相機(jī)與錄音,去河邊找鬼畏梆。 笑死您宪,一個(gè)胖子當(dāng)著我的面吹牛奈懒,可吹牛的內(nèi)容都是我干的。 我是一名探鬼主播宪巨,決...
    沈念sama閱讀 39,028評(píng)論 3 409
  • 文/蒼蘭香墨 我猛地睜開眼磷杏,長(zhǎng)吁一口氣:“原來是場(chǎng)噩夢(mèng)啊……” “哼!你這毒婦竟也來了捏卓?” 一聲冷哼從身側(cè)響起极祸,我...
    開封第一講書人閱讀 37,773評(píng)論 0 268
  • 序言:老撾萬榮一對(duì)情侶失蹤,失蹤者是張志新(化名)和其女友劉穎怠晴,沒想到半個(gè)月后遥金,有當(dāng)?shù)厝嗽跇淞掷锇l(fā)現(xiàn)了一具尸體,經(jīng)...
    沈念sama閱讀 44,220評(píng)論 1 303
  • 正文 獨(dú)居荒郊野嶺守林人離奇死亡蒜田,尸身上長(zhǎng)有42處帶血的膿包…… 初始之章·張勛 以下內(nèi)容為張勛視角 年9月15日...
    茶點(diǎn)故事閱讀 36,550評(píng)論 2 327
  • 正文 我和宋清朗相戀三年稿械,在試婚紗的時(shí)候發(fā)現(xiàn)自己被綠了。 大學(xué)時(shí)的朋友給我發(fā)了我未婚夫和他白月光在一起吃飯的照片冲粤。...
    茶點(diǎn)故事閱讀 38,697評(píng)論 1 341
  • 序言:一個(gè)原本活蹦亂跳的男人離奇死亡溜哮,死狀恐怖,靈堂內(nèi)的尸體忽然破棺而出色解,到底是詐尸還是另有隱情茂嗓,我是刑警寧澤,帶...
    沈念sama閱讀 34,360評(píng)論 4 332
  • 正文 年R本政府宣布科阎,位于F島的核電站述吸,受9級(jí)特大地震影響,放射性物質(zhì)發(fā)生泄漏锣笨。R本人自食惡果不足惜蝌矛,卻給世界環(huán)境...
    茶點(diǎn)故事閱讀 40,002評(píng)論 3 315
  • 文/蒙蒙 一、第九天 我趴在偏房一處隱蔽的房頂上張望错英。 院中可真熱鬧入撒,春花似錦、人聲如沸椭岩。這莊子的主人今日做“春日...
    開封第一講書人閱讀 30,782評(píng)論 0 21
  • 文/蒼蘭香墨 我抬頭看了看天上的太陽(yáng)判哥。三九已至献雅,卻和暖如春,著一層夾襖步出監(jiān)牢的瞬間塌计,已是汗流浹背挺身。 一陣腳步聲響...
    開封第一講書人閱讀 32,010評(píng)論 1 266
  • 我被黑心中介騙來泰國(guó)打工, 沒想到剛下飛機(jī)就差點(diǎn)兒被人妖公主榨干…… 1. 我叫王不留锌仅,地道東北人章钾。 一個(gè)月前我還...
    沈念sama閱讀 46,433評(píng)論 2 360
  • 正文 我出身青樓墙贱,卻偏偏與公主長(zhǎng)得像,于是被迫代替她去往敵國(guó)和親贱傀。 傳聞我的和親對(duì)象是個(gè)殘疾皇子惨撇,可洞房花燭夜當(dāng)晚...
    茶點(diǎn)故事閱讀 43,587評(píng)論 2 350