如何使用Golang Chromedp实现PDF下载且不存储到服务器
使用chromedp生成PDF并直接返回给客户端(不存储到服务器)
你当前的代码会将生成的PDF存储在服务器本地,要实现不存服务器直接让客户端下载的需求,只需要调整响应头并直接把PDF字节流返回给浏览器即可,核心修改如下:
关键修改点
- 删掉服务器本地存储PDF的
os.WriteFile代码块 - 替换最后返回JSON的逻辑,设置PDF专属的HTTP响应头
- 直接将chromedp生成的PDF字节流写入响应体
修改后的完整代码
import ( "context" "fmt" "log" "net/http" "strconv" "github.com/chromedp/chromedp" "github.com/chromedp/chromedp/kb" "github.com/gin-gonic/gin" "github.com/gorilla/sessions" ) func PDFInvoice(c *gin.Context) { session := sessions.Default(c) id := c.Params.ByName("id") token := session.Get("login_session").(string) // 创建chromedp上下文 ctx, cancel := chromedp.NewContext(context.Background()) defer cancel() // 生成PDF字节流 var buf []byte url := "http://localhost:8080/invoice/" + id + "/" + token if err := chromedp.Run(ctx, printToPDF(url, &buf)); err != nil { log.Printf("生成PDF失败: %v", err) c.AbortWithStatus(http.StatusInternalServerError) return } // 设置响应头,触发浏览器下载PDF c.Header("Content-Type", "application/pdf") // 自定义下载文件名,比如 invoice-xxx.pdf c.Header("Content-Disposition", fmt.Sprintf("attachment; filename=\"invoice-%s.pdf\"", id)) c.Header("Content-Length", strconv.Itoa(len(buf))) // 直接将PDF字节流返回给客户端 if _, err := c.Writer.Write(buf); err != nil { log.Printf("写入响应体失败: %v", err) c.AbortWithStatus(http.StatusInternalServerError) return } } // 生成PDF的工具函数(无需修改) func printToPDF(urlstr string, res *[]byte) chromedp.Tasks { return chromedp.Tasks{ chromedp.Navigate(urlstr), chromedp.ActionFunc(func(ctx context.Context) error { buf, _, err := page.PrintToPDF().WithPrintBackground(false).Do(ctx) if err != nil { return err } *res = buf return nil }), } }
代码说明
- 移除本地存储:彻底删除了
os.WriteFile相关代码,不再在服务器磁盘保存PDF文件 - 响应头配置:
Content-Type: application/pdf:告诉浏览器响应内容是PDF格式Content-Disposition: attachment; filename="xxx.pdf":强制触发浏览器的下载行为,同时指定用户下载后的文件名Content-Length:让浏览器提前知晓文件大小,优化下载体验
- 错误处理优化:把
log.Fatal改为打印日志并返回错误状态码,避免单个请求失败导致整个服务崩溃
内容的提问来源于stack exchange,提问作者Shakhawat Hossain
相关产品推荐
相关产品推荐

