gpt4 book ai didi

http - PDF 下载在 golang 的服务器端不起作用

转载 作者:IT王子 更新时间:2023-10-29 01:58:22 26 4
gpt4 key购买 nike

我在服务器端 (golang) 创建了 pdf,然后我想通过 api 调用下载该 pdf。我使用了 ajax post 请求。该请求直接进入以下 ExportReport 处理程序。但是我下载的pdf文档是空白页。由于请求 header 上的 Content-Length 设置而发生错误错误是:

 http: wrote more than the declared Content-Length
2016/12/20 14:37:39 http: multiple response.WriteHeader calls

此错误分解为 pdf 下载。请查看我的代码片段。

func ExportReport(w http.ResponseWriter, r *http.Request) *core_commons.AppError {

url := "https://mydomainname/reporting/repository/dashboard.pdf"

timeout := time.Duration(5) * time.Second
cfg := &tls.Config{
InsecureSkipVerify: true,
}
transport := &http.Transport{
TLSClientConfig: cfg,
ResponseHeaderTimeout: timeout,
Dial: func(network, addr string) (net.Conn, error) {
return net.DialTimeout(network, addr, timeout)
},
DisableKeepAlives: true,
}

client := &http.Client{
Transport: transport,
}
resp, err := client.Get(url)
if err != nil {
fmt.Println(err)
}
defer resp.Body.Close()

w.Header().Set("Content-Disposition", "attachment; filename=dashboard.pdf")
w.Header().Set("Content-Type", r.Header.Get("Content-Type"))
w.Header().Set("Content-Length", r.Header.Get("Content-Length"))

_, err = io.Copy(w, resp.Body)
if err != nil {
fmt.Println(err)
}
return nil
}

以下是如何调用ajax请求。

$.ajax({
type: "POST",
url: '/reporting/api/report/export',
data: JSON.stringify(payload),
contentType: 'application/pdf',
success: function(response, status, xhr) {
// check for a filename
var filename = "";
var disposition = xhr.getResponseHeader('Content-Disposition');
if (disposition && disposition.indexOf('attachment') !== -1) {
var filenameRegex = /filename[^;=\n]*=((['"]).*?\2|[^;\n]*)/;
var matches = filenameRegex.exec(disposition);
if (matches != null && matches[1]) filename = matches[1].replace(/['"]/g, '');
}

var type = xhr.getResponseHeader('Content-Type');
var blob = new Blob([response], { type: type });

if (typeof window.navigator.msSaveBlob !== 'undefined') {
// IE workaround for "HTML7007: One or more blob URLs were revoked by closing the blob for which they were created. These URLs will no longer resolve as the data backing the URL has been freed."
window.navigator.msSaveBlob(blob, filename);
} else {
var URL = window.URL || window.webkitURL;
var downloadUrl = URL.createObjectURL(blob);

if (filename) {
// use HTML5 a[download] attribute to specify filename
var a = document.createElement("a");
// safari doesn't support this yet
if (typeof a.download === 'undefined') {
window.location = downloadUrl;
} else {
a.href = downloadUrl;
a.download = filename;
document.body.appendChild(a);
a.click();
}
} else {
window.location = downloadUrl;
}

setTimeout(function () { URL.revokeObjectURL(downloadUrl); }, 100); // cleanup
}
}
});

最佳答案

看看这两行:

w.Header().Set("Content-Type", r.Header.Get("Content-Type"))
w.Header().Set("Content-Length", r.Header.Get("Content-Length"))

您想要设置与获取 PDF 时相同的内容类型和长度,但是 r 请求是与您服务 的请求相关联的请求!应该是:

w.Header().Set("Content-Type", resp.Header.Get("Content-Type"))
w.Header().Set("Content-Length", resp.Header.Get("Content-Length"))

另请注意,无法保证您调用的 URL 会设置 Content-Length,因此您应该只在响应中设置非零值。另请注意,也不能保证它发送的内容长度是正确的,因此您应该小心处理。另请注意,内容长度 header 由 net/http 包自动解析并存储在响应中,您可以只使用:Response.ContentLength .

如果您设置内容长度,net/http 包将不允许您发送比指示更多的字节。试图写更多会给你错误:

http: wrote more than the declared Content-Length

这个小例子证明/验证了它:

func h(w http.ResponseWriter, r *http.Request) {
w.Header().Set("Content-Length", "1")
fmt.Println(w.Write([]byte("hi")))
}

func main() {
http.HandleFunc("/", h)
panic(http.ListenAndServe(":8080", nil))
}

处理程序 h() 写入 2 个字节,但内容长度仅指示 1。如果将其更改为 2,一切正常。

所以你应该做的是首先检查 r.Header.Get("Content-Length") 它是否不是空的 string 并且是一个大于 0;并且只有在这样的情况下才进行设置。

如果接收到的内容长度缺失,而您仍想在响应中指明它,那么您别无选择,只能先将内容读入缓冲区,您可以在发送之前检查和设置缓冲区的长度。

您还忽略了检查 HTTP GET 请求是否成功。您的评论表明这是一个错误页面。首先检查:

resp, err := client.Get(url)
if err != nil {
fmt.Println(err)
http.Error(w, "Can't serve PDF.", http.StatusInternalServerError)
return
}
defer resp.Body.Close()

if resp.StatusCode != http.StatusOK {
http.Error(w, "Can't serve PDF.", http.StatusInternalServerError)
return
}

关于http - PDF 下载在 golang 的服务器端不起作用,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41238407/

26 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com