Golang Gin框架實現文件下載功能

Layui框架實現文件上傳

基本的思路就是隨便創建一個元素,然後使用layui的upload組件對創建的元素進行渲染,詳見代碼

<!DOCTYPE html>
<html lang="en">
<head>
    <script src="jquery-3.5.0.min.js" type="text/javascript"></script> <!-- jquery包,記得替換爲你本地的路徑 -->

    <link rel="stylesheet" href="layui/css/layui.css"> <!--layui框架的樣式庫 同樣你本地的路徑 -->
    <script src="pkg/layui/layui.js"></script><!--enmmm 沒錯,路徑-->
</head>	
<body>
<!-- 這裏我是用的a標籤,當然你可以使用別的 label、button等均可-->
 <a href="javascript:(0);" id="attachment-upload">+添加附件</a>
</body>
<script>
	//以layui.js的方式引入使用時需要手動加載layui的組件
	layui.use(['layer','upload'],function(){ // PS:個人理解,該行只是爲了引入layui框架的組件,html文件加載完畢後執行,內部的代碼和直接寫在script標籤內沒啥區別,只是可以在代碼中使用layer了
	// 此處引入layer只是爲了打印一些東西
		var layer = layui.layer,
		upload = layui.upload;
		
	// 渲染元素,使其支持文件上傳
	// 詳情請移步 https://www.layui.com/doc/modules/upload.html
	// https://www.layui.com/demo/upload.html
	 upload.render({
            elem: '#attachment-upload', // 感覺利用了jquery的id選擇器,這裏用#id(上傳附件的標籤、按鈕值類型元素id)就可以了
            url: dev_url + "fc/upload", // 後端接收上傳文件的接口地址
            headers: {   // 這裏官方文檔中沒有,是在請求後端接口時在request header中增加一些請求參數,實測可行
                'api_token': uInfo
            },
            accept: 'file', // 這裏可以限定支持上傳文件的類型,詳見文檔
            done: function (res) { // 調用後端上傳文件接口後的返回
           // 這裏解析下後端的返回字段,具體怎麼着看業務吧
                if (res.success == false) {
                    layer.msg("上傳文件失敗!" + res.msg);
                }
        });
})
</script>
</html>

PS:注意下使用layui上傳文件的請求格式爲multiply/form-data,參數爲file,(binary)格式

layui上傳文件組件請求

Gin框架獲取前端上傳的文件

func UploadFileControl(c *gin.Context) {
	logrus.Infof("[UploadFileControl] user_id =%d", userId)
	// GIN框架獲取前端上傳文件
	// 這裏的參數其實是上傳文件時的字段名,也就是上面圖片中的file,如果前端是自己定義的其他字段名,需要替換下
	uploadFile, fileHeader, err := c.Request.FormFile("file")
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"success": false,
			"msg":     "獲取文件信息失敗!" + err.Error(),
		})
	}
	if uploadFile != nil { // 記得及時關閉文件,避免內存泄漏
		defer uploadFile.Close()
	}

// 讀取上傳文件的內容
// 其實這裏直接讀取所有不太合理,如果文件過大時會佔用很多內存,可以考慮使用緩衝區讀取
	fileContent, err := ioutil.ReadAll(uploadFile)
	if err != nil {
		c.JSON(http.StatusOK, gin.H{
			"success": false,
			"msg":     "讀取文件內容失敗!" + err.Error(),
		})
	}

// 接受到文件後的處理方式,可以保存到本地,也可以上傳到文件對象,看自己了
	/*fileId, err := oss.GetOssClient().UploadFile(userId, fileHeader.Filename, fileContent)
	if err != nil {
		logrus.Errorf("[UploadFile] error,user_id = %d,err_msg= %s", userId, err.Error())
		c.JSON(http.StatusOK, gin.H{
			"success": false,
			"msg":     "上傳文件失敗!請稍後再試",
		})
	}*/

// 這裏向前端返回下上傳成功的信息
	c.JSON(http.StatusOK, gin.H{
		"success":   true,
		"msg":       "",
	})
}

Gin框架的文件下載

        Response Header中的Content-Type指定了服務器端返回數據的類型,瀏覽器自己是可以處理這些類型的,當返回的數據爲文件類型時,瀏覽器會自行下載。具體的類型和content-type的對應方式可見https://tool.oschina.net/commons/.
        當Content-Type是一些文件類型時,使用Content-Disposition可以指定瀏覽器下載文件時的默認文件名
        因此,我們想要使用gin實現下載文件的功能,只需要在接口返回時設置Response-Header中的Content-Type爲文件類型,並設置Content-Disposition指定默認的文件名,然後將文件數據返回瀏覽器即可,具體代碼如下:

func DownloadFileControl(c *gin.Context) {
	//  查詢一些必要的參數 進行一些必要的驗證
	attchIdStr := c.Query("attachment_id")
	attachmentName = c.Query("attachment_name")
	
	// 獲取要返回的文件數據流
	// 看你文件存在哪裏了,本地就直接os.Open就可以了,總之是要獲取一個[]byte
	/*	fileContent, err := oss.GetOssClient().DownloadFile(req.AttachmentId, req.AttachmentName)
	if err != nil {
		logrus.Errorf("[DownloadFile] download file error,file_id = %d,file_name = %s,user_is = %d,err_msg= %s", req.UserId, req.AttachmentId, req.AttachmentName, err.Error())
		c.JSON(http.StatusOK, gin.H{
			"success": false,
			"msg":     "下載文件失敗,請聯繫管理員",
		})
		return
	}*/
	
// 設置返回頭並返回數據
	fileContentDisposition := "attachment;filename=\"" + attachmentName + "\""
	c.Header("Content-Type", "application/zip") // 這裏是壓縮文件類型 .zip
	c.Header("Content-Disposition", fileContentDisposition)
	c.Data(http.StatusOK, contentType, fileContent)

PS:小白文,只是提供了一個親測有效的處理方式,如有錯誤或更好的方法,歡迎指正

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章