golang如何操作二进制流呢?

有一个需求是这样的:
需要用go从一个接口获取pdf文件,然后前端js向go请求这个pdf文件,最终在页面上显示一个预览按钮并可以点击预览pdf

前端 → go → pdf

具体是这么一个过程,pdf用二进制方式传递,具体如何实现呢。。?

阅读 10.3k
5 个回答

楼上的如果PDF过大,一次性读取会有内存问题。
另外,不要使用panic来中断逻辑运行,一旦panic没被处理,整个程序挂掉

func main() {
    http.HandleFunc("/pdf", function(w ResponseWriter, r *http.Request) {
        w.Header().Add("Content-Type", "application/pdf");
        fp, err:= os.Open("./go.pdf")
        if err!=nil {
            http.Error(w, fmt.Errorf("internal server error"), http.StatusInternalServerError)
            return;
        }
        defer fp.Close()
        
        if _, err:=io.Copy(w, fp);err!=nil {
            http.Error(w, fmt.Errorf("internal server error"), http.StatusInternalServerError)
           return;
        }
    });
}

根据 @loxp 的回答,写了测试代码。完全可行

func main() {
    http.HandleFunc("/index", IndexHandler)
    http.ListenAndServe(":8082", nil)
}

func IndexHandler(w http.ResponseWriter, r *http.Request) {
    w.Header().Add("Content-Type", "application/pdf")
    f, err := os.OpenFile("./go_book.pdf", os.O_RDONLY, 0777)
    if err != nil {
        // handle the error
    }
   defer f.Close()
   io.Copy(w, f)

    //b, err := ioutil.ReadAll(f)
    //if err != nil {
    //    panic(err)
    //}
   //w.Write(b)
}

访问http://127.0.0.1:8082/index就可以看到效果

主要是http返回的content-type吧, 设置成application/pdf就行了. go中二进制数据用[]byte保存就可以.

w.Header().Add("Content-Type", "application/pdf")
w.Header().Add("Content-Disposition", "attachment; filename=\""+fileNames+"\"")
经测试只设置    Content-Type即可,w.Header().Add("Content-Transfer-Encoding", "binary") 不是必须的,详情 https://www.w3.org/Protocols/rfc1341/5_Content-Transfer-Encoding.html
用 http.ServeFile() 也可实现下载显示
package main  
  
import (  
    "log"  
 "net/http" "os" "time")  
  
func main() {  
    http.HandleFunc("/", zipHandler)  
    log.Println("Listening......")  
    http.ListenAndServe(":8080", nil)  
}  
  
func zipHandler(rw http.ResponseWriter, r \*http.Request) {  
    rw.Header().Set("Content-Type", "application/pdf")  
    f, err := os.Open("./sample.pdf");  
    defer f.Close()  
    if err == nil {  
        for {  
            buf := make(\[\]byte, 1024)  
            \_, err := f.Read(buf);  
            if err == nil {  
                rw.Write(buf)  
                // 流控  
  time.Sleep(1000 \* time.Microsecond)  
            } else {  
                return  
  }  
  
        }  
    }  
  
}
撰写回答
你尚未登录,登录后可以
  • 和开发者交流问题的细节
  • 关注并接收问题和回答的更新提醒
  • 参与内容的编辑和改进,让解决方法与时俱进
推荐问题
宣传栏