英文:
Go HTTP will not set header for SVG
问题
我正在生成一个SVG(它将在一个单独的浏览器窗口中加载,检测到头部错误时),将内容类型设置为"image/svg+xml",然后写入SVG,但是当它发送到浏览器时,它以text/xml的形式显示。
我首先写入头部(这是这个问题的问题所在),在几个小时内毫无目的地移动代码后,我已经没有任何想法了。
这是我的代码:
const circlesize = 2.5
// http.HandleFunc("/rendermap.svg", rendermapw)
func rendermapw(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		w.WriteHeader(405)
		return
	}
	fmt.Println("Received request " + r.URL.String())
	var mapstring string
	// 已经渲染过
	if mapcache.valid {
		mapstring = mapcache.cache
	} else {
		// 获取模板
		contentb, err := ioutil.ReadFile("src/maptemplate.svg")
		if err != nil {
			fmt.Println("Error with request:", r)
			fmt.Println(err)
			w.WriteHeader(500)
			return
		}
		content := strings.Split(string(contentb), "<!--template-->")
		// 从数据库中获取数据
		alldata := *pullall()
		mapstring = content[0] // 头部
		for _, e := range alldata {
			newcircle := content[1]
			// 将uint64转换为字符串(将uint16转换为int64)
			newcircle = strings.Replace(newcircle, "{ulat}", strconv.FormatInt(int64(e.Ulat), 10), 1)
			newcircle = strings.Replace(newcircle, "{ulon}", strconv.FormatInt(180-int64(e.Ulon), 10), 1)
			newcircle = strings.Replace(newcircle, "{size}", strconv.FormatFloat(circlesize, 'f', 4, 64), 1)
			mapstring += newcircle
		}
		mapstring += content[2]
		// 保存缓存并发送
		mapcache = mapcached{
			valid: true,
			cache: mapstring,
		}
	}
    // 上面的所有代码都是有效的,我只是为了完整性而贴出来
	w.WriteHeader(200)
	w.Header().Set("content-type", "image/svg+xml")
	_, err := fmt.Fprint(w, mapstring) // 我也尝试过 w.Write([]byte(mapstring))
	if err != nil {
		fmt.Println("Error with request:", r)
		fmt.Println(err)
		w.WriteHeader(500)
		return
	}
}
这是发送到浏览器的内容:
Content-Type: text/xml; charset=utf-8
maptemplate.svg的内容如下:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 360 180" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" fill="#0098ff">
<!--template-->
<circle cx="{ulat}" cy="{ulon}" r="{size}" fill-opacity=".5"/>
<!--template-->
</svg>
如果我删除"<?xml version..."这一行,浏览器将收到text/plain类型的内容。
英文:
I'm generating an SVG (that will load in a separate browser window where it detects that the header is wrong), setting the content-type to "image/svg+xml", then writing the SVG, but when it is sent to the browser, it comes out as text/xml.
I'm writing the header first (which was the problem in this issue) and I'm out of ideas after moving stuff around aimlessly for a few hours.
Here is my code:
const circlesize = 2.5
// http.HandleFunc("/rendermap.svg", rendermapw)
func rendermapw(w http.ResponseWriter, r *http.Request) {
	if r.Method != "GET" {
		w.WriteHeader(405)
		return
	}
	fmt.Println("Received request " + r.URL.String())
	var mapstring string
	// already rendered
	if mapcache.valid {
		mapstring = mapcache.cache
	} else {
		// get template
		contentb, err := ioutil.ReadFile("src/maptemplate.svg")
		if err != nil {
			fmt.Println("Error with request:", r)
			fmt.Println(err)
			w.WriteHeader(500)
			return
		}
		content := strings.Split(string(contentb), "<!--template-->")
		// pull from database
		alldata := *pullall()
		mapstring = content[0] // header
		for _, e := range alldata {
			newcircle := content[1]
			//									   string from uint64 (int64 from uint16)
			newcircle = strings.Replace(newcircle, "{ulat}", strconv.FormatInt(int64(e.Ulat), 10), 1)
			newcircle = strings.Replace(newcircle, "{ulon}", strconv.FormatInt(180-int64(e.Ulon), 10), 1)
			newcircle = strings.Replace(newcircle, "{size}", strconv.FormatFloat(circlesize, 'f', 4, 64), 1)
			mapstring += newcircle
		}
		mapstring += content[2]
		// save cache & send
		mapcache = mapcached{
			valid: true,
			cache: mapstring,
		}
	}
    // everything above this works, I'm just posting it for completion's sake
	w.WriteHeader(200)
	w.Header().Set("content-type", "image/svg+xml")
	_, err := fmt.Fprint(w, mapstring) // I also tried w.Write([]byte(mapstring))
	if err != nil {
		fmt.Println("Error with request:", r)
		fmt.Println(err)
		w.WriteHeader(500)
		return
	}
}
This is what gets sent to the browser:
Content-Type: text/xml; charset=utf-8
Here is maptemplate.svg looks like:
<?xml version="1.0" encoding="utf-8"?>
<!DOCTYPE svg PUBLIC "-//W3C//DTD SVG 1.1//EN" "http://www.w3.org/Graphics/SVG/1.1/DTD/svg11.dtd">
<svg xmlns="http://www.w3.org/2000/svg" version="1.1" viewBox="0 0 360 180" fill-rule="evenodd" stroke-linejoin="round" stroke-miterlimit="2" fill="#0098ff">
<!--template-->
<circle cx="{ulat}" cy="{ulon}" r="{size}" fill-opacity=".5"/>
<!--template-->
</svg>
If I remove the "<?xml version..." line, the browser gets sent text/plain.
答案1
得分: 1
我已经修复了。在w.WriteHeader(200)之前,你必须添加w.Header().Set("content-type", "image/svg+xml")。
修复后的代码:
    // ...
	w.Header().Set("content-type", "image/svg+xml")
	w.WriteHeader(200)
	_, err := fmt.Fprint(w, mapstring)
	if err != nil {
		fmt.Println("请求错误:", r)
		fmt.Println(err)
		w.WriteHeader(500)
		return
	}
英文:
I fixed it. You have to have w.Header().Set("content-type", "image/svg+xml") before w.WriteHeader(200).
Working code:
    // ...
	w.Header().Set("content-type", "image/svg+xml")
	w.WriteHeader(200)
	_, err := fmt.Fprint(w, mapstring)
	if err != nil {
		fmt.Println("Error with request:", r)
		fmt.Println(err)
		w.WriteHeader(500)
		return
	}
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。


评论