package versionApi import ( "net/http" "stat/common/stdLog" "stat/service/cpcDownloadCfgSer" "stat/service/versionSer" "strconv" "strings" "github.com/gin-gonic/gin" ) // CpcDownload 双端下载 // @Tags 双端下载 // @Summary 双端下载 // @Description 记录下载历史。android:302跳转到下载地址(优先按appId+channel取配置,否则取最新);ios:返回mobileconfig配置文件 // @Produce octet-stream // @Param appId path int true "产品AppId" // @Param channel path string true "渠道(json字符串)" // @Param tid query string false "埋点traceID" // @Success 200 {file} file "ios返回mobileconfig文件" // @Success 302 {string} string "android跳转下载地址" // @Failure 400 {string} string "失败" // @Router /rsdownload/{appId}/{channel} [get] func CpcDownload(ctx *gin.Context) { // 第一个参数 appId appId, err := strconv.Atoi(ctx.Param("appId")) if err != nil { stdLog.ServerJSON(ctx, stdLog.ParamError, err.Error()) return } // 第二个参数 channel(渠道,json字符串) channel := ctx.Param("channel") userAgent := ctx.Request.Header.Get("User-Agent") isIos := strings.Contains(userAgent, "iPhone") || strings.Contains(userAgent, "iPad") // 记录下载历史(双端都记) versionSer.RecordCpcDownload(ctx, isIos, int32(appId), channel, ctx.ClientIP(), userAgent) // ios: 优先按appId和渠道查询双端配置的落地页,配置了落地页则301跳转,否则返回mobileconfig配置文件 if isIos { landingPage := cpcDownloadCfgSer.GetLandingPage(ctx, int32(appId), channel) if len(landingPage) > 0 { // 落地页未带dc参数时,拼上当前渠道 if !strings.Contains(landingPage, "dc=") { if strings.Contains(landingPage, "?") { landingPage = landingPage + "&dc=" + channel } else { landingPage = landingPage + "?dc=" + channel } } ctx.Redirect(http.StatusMovedPermanently, landingPage) return } cfg := versionSer.IosMobileconfigByAppId(int32(appId)) if cfg == nil { stdLog.ServerJSON(ctx, stdLog.Failure, "ios config不存在") return } pc, dc, _ := versionSer.ParseChannel(channel) writeMobileconfig(ctx, cfg, dc, pc) return } // android: 优先按appId和channel查询配置的下载链接,没有则使用默认最新下载地址 downloadUrl := cpcDownloadCfgSer.GetDownloadUrl(ctx, int32(appId), channel) if downloadUrl == "" { downloadUrl = versionSer.LatestAndroidDownloadUrl(int32(appId)) } if downloadUrl == "" { stdLog.ServerJSON(ctx, stdLog.Failure, "android下载地址不存在") return } ctx.Redirect(http.StatusFound, downloadUrl) } // writeMobileconfig 将 mobileconfig 文件以附件形式写入响应 func writeMobileconfig(ctx *gin.Context, cfg *versionSer.IosMobileconfigCfg, dc, pc string) { data, fileName := versionSer.BuildMobileconfig(cfg, dc, pc) if fileName == "" { fileName = "madou.mobileconfig" } ctx.Header("Content-Type", "application/octet-stream") ctx.Header("Content-Disposition", "attachment; filename="+fileName) ctx.Header("Content-Transfer-Encoding", "binary") _, _ = ctx.Writer.Write(data) }