背景
有一个需求,可以通过点击按钮下载apk到pc端,也可以出现一个二维码,手机端扫描二维码下载文件,通过go语言实现
实现
点击下载
我用的是gin框架,只需要输出到上下文即可下载。用过php的都知道,下载有个最简单的办法,将内容echo出来即可。
1 查询apk文件的Content-Type,content-type对照表,找到apk对应application/vnd.android.package-archive
2 编写下载代码,测试,发现必须有Content-Length属性,否则手机端会显示文件大小未知
代码如下:
// HandleDownloadFIle 下载文件
func HandleDownloadFIle (c *gin.Context, fname string) {
c.Writer.WriteHeader(http.StatusOK)
c.Header("Content-Disposition", "attachment; filename="+fname)
c.Header("Content-Type", "application/vnd.android.package-archive")
readF, _ := file.Open(fname, syscall.O_RDONLY, 0666)
var content []byte
buf := make([]byte, 1024)
for {
myLen, _ := readFile.Read(buf)
if myLen== 0 {
break
}
content = append(content, buf...)
}
sum := len(content)
c.Header("Content-Length", strconv.Itoa(sum)) // 这里我试过readFile.State().Size(),不准确,无法下载
c.Writer.Write(content)
readF.Close()
}
二维码下载
其实可以直接链接到上一个下载地址即可,生成二维码就行了,我引入了"github.com/skip2/go-qrcode"
这个包,LocalIPv4s这个方法是用来获取本地的ip列表,很简单,略,一般最后一个是内网ip。
代码:
// QrcodeDown 下载二维码
func QrcodeDown(c *gin.Context) error {
urls, err := LocalIPv4s()
if len(urls) < 1 {
return errors.New("无法获取下载地址")
}
if err != nil {
return err
}
url := "http://" + urls[len(urls)-1] + "/old_download" // 这里拼接的是旧的下载地址
qrcode.WriteFile(url, qrcode.High, 256, "my_qrcode.png")
readF, _ := file.Open("my_qrcode.png", syscall.O_RDONLY, 0666)
c.Writer.WriteHeader(http.StatusOK)
c.Header("Content-Disposition", "attachment; filename=my_qrcode.png")
c.Header("Content-Type", "image/png")
var content []byte
buf := make([]byte, 1024)
for {
tmpLen, _ := readF.Read(buf)
if tmpLen == 0 {
break
}
content = append(content, buf...)
}
c.Writer.Write(content)
readF.Close()
return nil
}