go下载excel文件流接口前端跨域请求错误问题解决

好久未更新,最近的go项目需要后端提供下载excel的二进制文件流,写完前端调用时出现跨域请求错误问题,就此记录一下错误和解决方式以及部分代码

一、问题暴露

go下载excel文件流接口前端跨域请求错误问题解决_第1张图片

二、问题解决

我的问题是:接口请求拦截未返回json数据的接口没有放开

//把不返回json数据的router路径添加到此处
var Fileter = []string{
	"/admin/v1/orders_down",
}
func CommonReturn(c *gin.Context) {
	c.Next()
	Uri := c.Request.URL.Path
	if ok := utils.IsExistString(Uri, Fileter); ok {
		return
	}
	if c.Writer.Status() == 404 {
		c.Abort()
		return
	}
	data := ctl.GetData(c)
	if len(data.Msg) == 0 {
		ctl.GetErrMsg(data, data.Ret)
	}
	//统一返回数据
	c.JSON(200, data)
}

var originMap map[string]int

func init() {
	var url = conf.GetString("originUrl")
	originMap = map[string]int{
		"maniujk-app":  1,
		"mgmt" + url:   1,
		"agent" + url:  1,
		"member" + url: 1,
		"vfqq" + url:   1,
	}
}

func Core() gin.HandlerFunc {
	return func(c *gin.Context) {
		method := c.Request.Method
		c.Header("Access-Control-Allow-Origin", "*")
		c.Header("Access-Control-Allow-Headers", "Content-Type,AccessToken,X-CSRF-Token, Authorization, Token,Tgt")
		//c.Header("Access-Control-Allow-Methods", "POST, GET, OPTIONS, PUT, PATCH, DELETE")
		c.Header("Access-Control-Allow-Methods", "POST, GET")
		c.Header("Access-Control-Expose-Headers", "Content-Length, Access-Control-Allow-Origin, Access-Control-Allow-Headers, Content-Type")
		c.Header("Access-Control-Allow-Credentials", "true")

		// 放行所有OPTIONS方法,因为有的模板是要请求两次的
		if method == "OPTIONS" {
			c.AbortWithStatus(http.StatusNoContent)
		}
		// 处理请求
		c.Next()
	}
}

ps:还有一种可能性参考

/*
		下方这种方式应对处理 这种bug:http: wrote more than the declared Content-Length
	*/
	//extraHeaders := map[string]string{
	//	"Content-Disposition": fmt.Sprintf(`attachment; filename="%s"`, "保险箱"),
	//}
	//c.DataFromReader(http.StatusOK, int64(contentLength), "application/xlsx", excel, extraHeaders)

三、相关代码

excel生成公共方法,可放在util工具类中

// DataToExcel 数据导出excel,titleList为表头数组 dataList里面的对象为指针
func DataToExcel(titleList []string, dataList []interface{}) *bytes.Reader {
	// 生成一个新的文件
	file := xlsx.NewFile()
	// 添加sheet页
	sheet, _ := file.AddSheet("Sheet1")
	// 插入表头
	titleRow := sheet.AddRow()
	for _, v := range titleList {
		cell := titleRow.AddCell()
		cell.Value = v
		cell.GetStyle().Font.Color = "00FF0000"
	}
	// 插入内容
	for _, v := range dataList {
		row := sheet.AddRow()
		row.WriteStruct(v, -1)
	}

	var buffer bytes.Buffer
	_ = file.Write(&buffer)
	content := bytes.NewReader(buffer.Bytes())
	//返回一个二进制文件流
	return content
}

controller调用

func DownExcel(c *gin.Context)  {
	data := ctl.NewSetData(c)
	orderList := m_order.OrderList{}
	err := c.ShouldBindJSON(&orderList)
	if err != nil {
		data.Ret = ctl.ErrorArgs
		return
	}
	titleList := []string{"会员ID", "会员有效期", "开通时间", "上次登录时间"}
	var dataList []interface{}
	for _,v:=range orderList.OrderList{
		dataList = append(dataList,v)
	}
	//返回excel 二进制文件流
	excel := utils.DataToExcel(titleList, dataList)

	var fileName ="文件名称"
	fileName = fmt.Sprintf("%s.xlsx", fileName)

	c.Writer.Header().Add("Content-Disposition", fmt.Sprintf(`attachment; filename="%s"`, fileName))
	c.Writer.Header().Add("Content-Type", "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet")

	http.ServeContent(c.Writer, c.Request, fileName, time.Now(), excel)
	return
}

db中需要接收数据

// 运营查看的数据
type ProStatus struct {
	UserId        string `json:"user_id" xorm:"comment('用户id') VARCHAR(128)"`
	PackageName   string `json:"package_name" xorm:"comment('套餐名') VARCHAR(128)"`
	CreatedTime   int64  `json:"created_time" xorm:"comment('创建时间')"`
	LastLoginTime int64  `json:"last_login_time"`
}

//用于接收前端导入excel 数据
type OrderList struct {
	OrderList []*ProStatus `json:"order_list"`
}

 

你可能感兴趣的:(go,go)