英文:
How to get the size of an io.reader object
问题
我想要获取io.reader的大小,以便返回一个base64图片的长度。
主要问题是获取解码后的大小,以返回一个content-length头。
以下是我的代码:
package main
import (
"fmt"
"net/http"
"time"
"strconv"
"io"
"encoding/base64"
"bytes"
)
func pix(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
cookie, _ := r.Cookie("csrftoken")
fmt.Printf(cookie.Value)
}
func img(w http.ResponseWriter, r *http.Request) {
expiration := time.Now().Add(365 * 24 * time.Hour)
cookie := http.Cookie{Name: "csrftoken", Value: "abcd", Expires: expiration, HttpOnly: false}
http.SetCookie(w, &cookie)
img := bytes.NewBufferString("iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAIAAACRXR/mAAADMUlEQVRYw+2YTUgUYRjHZzOJIoNA+rrUyYNIRQgRHaLo4qFDBEGeunSxS9TFU0QEnhIh6IvokrUzO2uamRmbG6XmR/mVaKZpZVbYvvO143zszsxOz+yahNm+785sITEP72F3Z+adH8/zf5+PpagwtxKXj+Vj+Vg+lo/lY+W+WI4KpddKwWIQFUSF97nNLcLGZt75SiOHchEXfskDVmYjlowpiEoei3UT2ljcFJOpOd169C1Z2SuvgsdpB7cgzB16EV/byGM2xDIVPxQujKmBDF/2m2l0vFvmEin7N2v8kiiPiOeGlGHRvP1RdxA9eYtGR7pk2Pf6lI7RCoP2RaWkZWe3fsFc18hvesAHPGEFUc24ltnx3kyiCJwfRMs6dTXLdSIjO9Osal18qzKfE5V9coDxhlU7qS3uOyiaB55JDtkS2TKoLCLaOLPS4b02pQdCHiUfRKf653/d2kjZN6f10jYxI2EnrGk5H+2WsVi6ZZ8fVSmGQKaYyyFuR6ugmUtVrJo2C7HokeGq8447sYpOPBbo3XFzKC95626sZlz905sUM9XLGbXvtKtTOhZrQDApkhNNkiAOPo/viojh2YSZsj1aF2eQ5n2stuomNQjiiGQanrFufdCXP8gu8tbhjridJ6saVPKExXJrwlwfb3pnAg2Ut0tEBZFI8gza81Tik15DCDIoINQ7aQdBo90RMfrdwNaWLFY9opJGkBQrhCA/HXspQ8W1XHkN6vfWFiGH9ouwhdpJUFuy2JX3eg6uyqENpNHZYcUd02jcLMI2WO67UwZVv1G1HLMq3L83KuEbLPdY7IL2L42p0MMQiuzkq/ncwucOi6qPbWkWoPfCUsENpweUnP1EmE4XGhgagT72RyXolkSCHBbTU3By3fgJj8VyJW3CmSHl8oTWMJuYUUizVvtcsuyJ6J4J663CMLevXar/lJgnKNSgbphzKjriTn5i0F8eX9ODXnEzf6JHvjGtv+aNGdWCOEKnJRmpr5oFVQV8WTWglIKHMlPhv5uqQ1xGYfB5fRMPo+n2VmFbi7ChiS9oWBhZvXrI01TNLg7yPxt51v9rxMfysXwsH8vH+g+wfgDUr+5LcyNV4AAAAABJRU5ErkJggg==")
dec := base64.NewDecoder(base64.StdEncoding, img)
w.Header().Set("Content-Type", "image/jpeg")
// 问题在这里,我想要获取大小以返回图片的长度(len(dec))
w.Header().Set("Content-Length", strconv.Itoa(len(dec)))
io.Copy(w, dec)
}
func main() {
http.HandleFunc("/pix/", pix)
http.HandleFunc("/img/", img)
http.HandleFunc("/red/", img)
http.HandleFunc("/", img)
http.ListenAndServe(":8080", nil)
}
祝好!谢谢。
英文:
I would like to get the size of an io.reader to return the length of a picture for a bse64 concerns.
The main problem is to get the size of dec to return a content-length header
Here is my code :
<!-- language: lang-golang -->
package main
import (
"fmt"
"net/http"
"time"
"strconv"
"io"
base64 "encoding/base64"
"bytes"
)
func pix(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
cookie, _ := r.Cookie("csrftoken")
fmt.Printf(cookie.Value)
}
func img(w http.ResponseWriter, r *http.Request) {
expiration := time.Now().Add(365 * 24 * time.Hour)
cookie := http.Cookie{Name: "csrftoken",Value:"abcd",Expires:expiration,HttpOnly: false}
http.SetCookie(w, &cookie)
img := bytes.NewBufferString("iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAIAAACRXR/mAAADMUlEQVRYw+2YTUgUYRjHZzOJIoNA+rrUyYNIRQgRHaLo4qFDBEGeunSxS9TFU0QEnhIh6IvokrUzO2uamRmbG6XmR/mVaKZpZVbYvvO143zszsxOz+yahNm+785sITEP72F3Z+adH8/zf5+PpagwtxKXj+Vj+Vg+lo/lY+W+WI4KpddKwWIQFUSF97nNLcLGZt75SiOHchEXfskDVmYjlowpiEoei3UT2ljcFJOpOd169C1Z2SuvgsdpB7cgzB16EV/byGM2xDIVPxQujKmBDF/2m2l0vFvmEin7N2v8kiiPiOeGlGHRvP1RdxA9eYtGR7pk2Pf6lI7RCoP2RaWkZWe3fsFc18hvesAHPGEFUc24ltnx3kyiCJwfRMs6dTXLdSIjO9Osal18qzKfE5V9coDxhlU7qS3uOyiaB55JDtkS2TKoLCLaOLPS4b02pQdCHiUfRKf653/d2kjZN6f10jYxI2EnrGk5H+2WsVi6ZZ8fVSmGQKaYyyFuR6ugmUtVrJo2C7HokeGq8447sYpOPBbo3XFzKC95626sZlz905sUM9XLGbXvtKtTOhZrQDApkhNNkiAOPo/viojh2YSZsj1aF2eQ5n2stuomNQjiiGQanrFufdCXP8gu8tbhjridJ6saVPKExXJrwlwfb3pnAg2Ut0tEBZFI8gza81Tik15DCDIoINQ7aQdBo90RMfrdwNaWLFY9opJGkBQrhCA/HXspQ8W1XHkN6vfWFiGH9ouwhdpJUFuy2JX3eg6uyqENpNHZYcUd02jcLMI2WO67UwZVv1G1HLMq3L83KuEbLPdY7IL2L42p0MMQiuzkq/ncwucOi6qPbWkWoPfCUsENpweUnP1EmE4XGhgagT72RyXolkSCHBbTU3By3fgJj8VyJW3CmSHl8oTWMJuYUUizVvtcsuyJ6J4J663CMLevXar/lJgnKNSgbphzKjriTn5i0F8eX9ODXnEzf6JHvjGtv+aNGdWCOEKnJRmpr5oFVQV8WTWglIKHMlPhv5uqQ1xGYfB5fRMPo+n2VmFbi7ChiS9oWBhZvXrI01TNLg7yPxt51v9rxMfysXwsH8vH+g+wfgDUr+5LcyNV4AAAAABJRU5ErkJggg==")
dec := base64.NewDecoder(base64.StdEncoding, img)
w.Header().Set("Content-Type", "image/jpeg")
// the problem is here i would like to get the size to return the length of the picture (lend(dec))
w.Header().Set("Content-Length", strconv.Itoa(len(dec)))
io.Copy(w, dec)
}
func main() {
http.HandleFunc("/pix/", pix)
http.HandleFunc("/img/", img)
http.HandleFunc("/red/", img)
http.HandleFunc("/", img)
http.ListenAndServe(":8080", nil)
}
regards and thanks
答案1
得分: 10
由于io.Reader
接口不知道底层数据的大小或长度,有两种选择:
- 使用缓冲区读取或复制所有数据。
buf := &bytes.Buffer{}
nRead, err := io.Copy(buf, dec)
if err != nil {
fmt.Println(err)
}
w.Header().Set("Content-Length", strconv.FormatInt(nRead, 10)) //len(dec)
这是一个可行的示例代码:
package main
import (
"bytes"
base64 "encoding/base64"
"fmt"
"io"
"net/http"
"strconv"
"time"
)
func pix(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
cookie, _ := r.Cookie("csrftoken")
fmt.Printf(cookie.Value)
}
func img(w http.ResponseWriter, r *http.Request) {
expiration := time.Now().Add(365 * 24 * time.Hour)
cookie := http.Cookie{Name: "csrftoken", Value: "abcd", Expires: expiration, HttpOnly: false}
http.SetCookie(w, &cookie)
img := bytes.NewBufferString("iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAIAAACRXR/mAAADMUlEQVRYw+2YTUgUYRjHZzOJIoNA+rrUyYNIRQgRHaLo4qFDBEGeunSxS9TFU0QEnhIh6IvokrUzO2uamRmbG6XmR/mVaKZpZVbYvvO143zszsxOz+yahNm+785sITEP72F3Z+adH8/zf5+PpagwtxKXj+Vj+Vg+lo/lY+W+WI4KpddKwWIQFUSF97nNLcLGZt75SiOHchEXfskDVmYjlowpiEoei3UT2ljcFJOpOd169C1Z2SuvgsdpB7cgzB16EV/byGM2xDIVPxQujKmBDF/2m2l0vFvmEin7N2v8kiiPiOeGlGHRvP1RdxA9eYtGR7pk2Pf6lI7RCoP2RaWkZWe3fsFc18hvesAHPGEFUc24ltnx3kyiCJwfRMs6dTXLdSIjO9Osal18qzKfE5V9coDxhlU7qS3uOyiaB55JDtkS2TKoLCLaOLPS4b02pQdCHiUfRKf653/d2kjZN6f10jYxI2EnrGk5H+2WsVi6ZZ8fVSmGQKaYyyFuR6ugmUtVrJo2C7HokeGq8447sYpOPBbo3XFzKC95626sZlz905sUM9XLGbXvtKtTOhZrQDApkhNNkiAOPo/viojh2YSZsj1aF2eQ5n2stuomNQjiiGQanrFufdCXP8gu8tbhjridJ6saVPKExXJrwlwfb3pnAg2Ut0tEBZFI8gza81Tik15DCDIoINQ7aQdBo90RMfrdwNaWLFY9opJGkBQrhCA/HXspQ8W1XHkN6vfWFiGH9ouwhdpJUFuy2JX3eg6uyqENpNHZYcUd02jcLMI2WO67UwZVv1G1HLMq3L83KuEbLPdY7IL2L42p0MMQiuzkq/ncwucOi6qPbWkWoPfCUsENpweUnP1EmE4XGhgagT72RyXolkSCHBbTU3By3fgJj8VyJW3CmSHl8oTWMJuYUUizVvtcsuyJ6J4J663CMLevXar/lJgnKNSgbphzKjriTn5i0F8eX9ODXnEzf6JHvjGtv+aNGdWCOEKnJRmpr5oFVQV8WTWglIKHMlPhv5uqQ1xGYfB5fRMPo+n2VmFbi7ChiS9oWBhZvXrI01TNLg7yPxt51v9rxMfysXwsH8vH+g+wfgDUr+5LcyNV4AAAAABJRU5ErkJggg==")
dec := base64.NewDecoder(base64.StdEncoding, img)
w.Header().Set("Content-Type", "image/jpeg")
buf := &bytes.Buffer{}
nRead, err := io.Copy(buf, dec)
if err != nil {
fmt.Println(err)
}
w.Header().Set("Content-Length", strconv.FormatInt(nRead, 10)) //len(dec)
io.Copy(w, buf)
}
func main() {
http.HandleFunc("/pix/", pix)
http.HandleFunc("/img/", img)
http.HandleFunc("/red/", img)
http.HandleFunc("/", img)
http.ListenAndServe(":8080", nil)
}
- 不设置头部大小,如下工作示例代码:
package main
import (
"bytes"
base64 "encoding/base64"
"fmt"
"io"
"net/http"
"time"
)
func pix(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
cookie, _ := r.Cookie("csrftoken")
fmt.Printf(cookie.Value)
}
func img(w http.ResponseWriter, r *http.Request) {
expiration := time.Now().Add(365 * 24 * time.Hour)
cookie := http.Cookie{Name: "csrftoken", Value: "abcd", Expires: expiration, HttpOnly: false}
http.SetCookie(w, &cookie)
img := bytes.NewBufferString("iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAIAAACRXR/mAAADMUlEQVRYw+2YTUgUYRjHZzOJIoNA+rrUyYNIRQgRHaLo4qFDBEGeunSxS9TFU0QEnhIh6IvokrUzO2uamRmbG6XmR/mVaKZpZVbYvvO143zszsxOz+yahNm+785sITEP72F3Z+adH8/zf5+PpagwtxKXj+Vj+Vg+lo/lY+W+WI4KpddKwWIQFUSF97nNLcLGZt75SiOHchEXfskDVmYjlowpiEoei3UT2ljcFJOpOd169C1Z2SuvgsdpB7cgzB16EV/byGM2xDIVPxQujKmBDF/2m2l0vFvmEin7N2v8kiiPiOeGlGHRvP1RdxA9eYtGR7pk2Pf6lI7RCoP2RaWkZWe3fsFc18hvesAHPGEFUc24ltnx3kyiCJwfRMs6dTXLdSIjO9Osal18qzKfE5V9coDxhlU7qS3uOyiaB55JDtkS2TKoLCLaOLPS4b02pQdCHiUfRKf653/d2kjZN6f10jYxI2EnrGk5H+2WsVi6ZZ8fVSmGQKaYyyFuR6ugmUtVrJo2C7HokeGq8447sYpOPBbo3XFzKC95626sZlz905sUM9XLGbXvtKtTOhZrQDApkhNNkiAOPo/viojh2YSZsj1aF2eQ5n2stuomNQjiiGQanrFufdCXP8gu8tbhjridJ6saVPKExXJrwlwfb3pnAg2Ut0tEBZFI8gza81Tik15DCDIoINQ7aQdBo90RMfrdwNaWLFY9opJGkBQrhCA/HXspQ8W1XHkN6vfWFiGH9ouwhdpJUFuy2JX3eg6uyqENpNHZYcUd02jcLMI2WO67UwZVv1G1HLMq3L83KuEbLPdY7IL2L42p0MMQiuzkq/ncwucOi6qPbWkWoPfCUsENpweUnP1EmE4XGhgagT72RyXolkSCHBbTU3By3fgJj8VyJW3CmSHl8oTWMJuYUUizVvtcsuyJ6J4J663CMLevXar/lJgnKNSgbphzKjriTn5i0F8eX9ODXnEzf6JHvjGtv+aNGdWCOEKnJRmpr5oFVQV8WTWglIKHMlPhv5uqQ1xGYfB5fRMPo+n2VmFbi7ChiS9oWBhZvXrI01TNLg7yPxt51v9rxMfysXwsH8vH+g+wfgDUr+5LcyNV4AAAAABJRU5ErkJggg==")
dec := base64.NewDecoder(base64.StdEncoding, img)
w.Header().Set("Content-Type", "image/jpeg")
io.Copy(w, dec)
}
func main() {
http.HandleFunc("/pix/", pix)
http.HandleFunc("/img/", img)
http.HandleFunc("/red/", img)
http.HandleFunc("/", img)
http.ListenAndServe(":8080", nil)
}
英文:
Since io.Reader
interface doesn't know anything about size or length of underlying data,
there are 2 options:
1- Use buffer and read or copy all data:
<!-- language: lang-golang -->
buf := &bytes.Buffer{}
nRead, err := io.Copy(buf, dec)
if err != nil {
fmt.Println(err)
}
w.Header().Set("Content-Length", strconv.FormatInt(nRead, 10)) //len(dec)
Like this working sample code:
<!-- language: lang-golang -->
package main
import (
"bytes"
base64 "encoding/base64"
"fmt"
"io"
"net/http"
"strconv"
"time"
)
func pix(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
cookie, _ := r.Cookie("csrftoken")
fmt.Printf(cookie.Value)
}
func img(w http.ResponseWriter, r *http.Request) {
expiration := time.Now().Add(365 * 24 * time.Hour)
cookie := http.Cookie{Name: "csrftoken", Value: "abcd", Expires: expiration, HttpOnly: false}
http.SetCookie(w, &cookie)
img := bytes.NewBufferString("iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAIAAACRXR/mAAADMUlEQVRYw+2YTUgUYRjHZzOJIoNA+rrUyYNIRQgRHaLo4qFDBEGeunSxS9TFU0QEnhIh6IvokrUzO2uamRmbG6XmR/mVaKZpZVbYvvO143zszsxOz+yahNm+785sITEP72F3Z+adH8/zf5+PpagwtxKXj+Vj+Vg+lo/lY+W+WI4KpddKwWIQFUSF97nNLcLGZt75SiOHchEXfskDVmYjlowpiEoei3UT2ljcFJOpOd169C1Z2SuvgsdpB7cgzB16EV/byGM2xDIVPxQujKmBDF/2m2l0vFvmEin7N2v8kiiPiOeGlGHRvP1RdxA9eYtGR7pk2Pf6lI7RCoP2RaWkZWe3fsFc18hvesAHPGEFUc24ltnx3kyiCJwfRMs6dTXLdSIjO9Osal18qzKfE5V9coDxhlU7qS3uOyiaB55JDtkS2TKoLCLaOLPS4b02pQdCHiUfRKf653/d2kjZN6f10jYxI2EnrGk5H+2WsVi6ZZ8fVSmGQKaYyyFuR6ugmUtVrJo2C7HokeGq8447sYpOPBbo3XFzKC95626sZlz905sUM9XLGbXvtKtTOhZrQDApkhNNkiAOPo/viojh2YSZsj1aF2eQ5n2stuomNQjiiGQanrFufdCXP8gu8tbhjridJ6saVPKExXJrwlwfb3pnAg2Ut0tEBZFI8gza81Tik15DCDIoINQ7aQdBo90RMfrdwNaWLFY9opJGkBQrhCA/HXspQ8W1XHkN6vfWFiGH9ouwhdpJUFuy2JX3eg6uyqENpNHZYcUd02jcLMI2WO67UwZVv1G1HLMq3L83KuEbLPdY7IL2L42p0MMQiuzkq/ncwucOi6qPbWkWoPfCUsENpweUnP1EmE4XGhgagT72RyXolkSCHBbTU3By3fgJj8VyJW3CmSHl8oTWMJuYUUizVvtcsuyJ6J4J663CMLevXar/lJgnKNSgbphzKjriTn5i0F8eX9ODXnEzf6JHvjGtv+aNGdWCOEKnJRmpr5oFVQV8WTWglIKHMlPhv5uqQ1xGYfB5fRMPo+n2VmFbi7ChiS9oWBhZvXrI01TNLg7yPxt51v9rxMfysXwsH8vH+g+wfgDUr+5LcyNV4AAAAABJRU5ErkJggg==")
dec := base64.NewDecoder(base64.StdEncoding, img)
w.Header().Set("Content-Type", "image/jpeg")
buf := &bytes.Buffer{}
nRead, err := io.Copy(buf, dec)
if err != nil {
fmt.Println(err)
}
w.Header().Set("Content-Length", strconv.FormatInt(nRead, 10)) //len(dec)
io.Copy(w, buf)
}
func main() {
http.HandleFunc("/pix/", pix)
http.HandleFunc("/img/", img)
http.HandleFunc("/red/", img)
http.HandleFunc("/", img)
http.ListenAndServe(":8080", nil)
}
2- Don't set the header size, like this working sample code:
<!-- language: lang-golang -->
package main
import (
"bytes"
base64 "encoding/base64"
"fmt"
"io"
"net/http"
"time"
)
func pix(w http.ResponseWriter, r *http.Request) {
fmt.Fprintf(w, "Hi there, I love %s!", r.URL.Path[1:])
cookie, _ := r.Cookie("csrftoken")
fmt.Printf(cookie.Value)
}
func img(w http.ResponseWriter, r *http.Request) {
expiration := time.Now().Add(365 * 24 * time.Hour)
cookie := http.Cookie{Name: "csrftoken", Value: "abcd", Expires: expiration, HttpOnly: false}
http.SetCookie(w, &cookie)
img := bytes.NewBufferString("iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAIAAACRXR/mAAADMUlEQVRYw+2YTUgUYRjHZzOJIoNA+rrUyYNIRQgRHaLo4qFDBEGeunSxS9TFU0QEnhIh6IvokrUzO2uamRmbG6XmR/mVaKZpZVbYvvO143zszsxOz+yahNm+785sITEP72F3Z+adH8/zf5+PpagwtxKXj+Vj+Vg+lo/lY+W+WI4KpddKwWIQFUSF97nNLcLGZt75SiOHchEXfskDVmYjlowpiEoei3UT2ljcFJOpOd169C1Z2SuvgsdpB7cgzB16EV/byGM2xDIVPxQujKmBDF/2m2l0vFvmEin7N2v8kiiPiOeGlGHRvP1RdxA9eYtGR7pk2Pf6lI7RCoP2RaWkZWe3fsFc18hvesAHPGEFUc24ltnx3kyiCJwfRMs6dTXLdSIjO9Osal18qzKfE5V9coDxhlU7qS3uOyiaB55JDtkS2TKoLCLaOLPS4b02pQdCHiUfRKf653/d2kjZN6f10jYxI2EnrGk5H+2WsVi6ZZ8fVSmGQKaYyyFuR6ugmUtVrJo2C7HokeGq8447sYpOPBbo3XFzKC95626sZlz905sUM9XLGbXvtKtTOhZrQDApkhNNkiAOPo/viojh2YSZsj1aF2eQ5n2stuomNQjiiGQanrFufdCXP8gu8tbhjridJ6saVPKExXJrwlwfb3pnAg2Ut0tEBZFI8gza81Tik15DCDIoINQ7aQdBo90RMfrdwNaWLFY9opJGkBQrhCA/HXspQ8W1XHkN6vfWFiGH9ouwhdpJUFuy2JX3eg6uyqENpNHZYcUd02jcLMI2WO67UwZVv1G1HLMq3L83KuEbLPdY7IL2L42p0MMQiuzkq/ncwucOi6qPbWkWoPfCUsENpweUnP1EmE4XGhgagT72RyXolkSCHBbTU3By3fgJj8VyJW3CmSHl8oTWMJuYUUizVvtcsuyJ6J4J663CMLevXar/lJgnKNSgbphzKjriTn5i0F8eX9ODXnEzf6JHvjGtv+aNGdWCOEKnJRmpr5oFVQV8WTWglIKHMlPhv5uqQ1xGYfB5fRMPo+n2VmFbi7ChiS9oWBhZvXrI01TNLg7yPxt51v9rxMfysXwsH8vH+g+wfgDUr+5LcyNV4AAAAABJRU5ErkJggg==")
dec := base64.NewDecoder(base64.StdEncoding, img)
w.Header().Set("Content-Type", "image/jpeg")
io.Copy(w, dec)
}
func main() {
http.HandleFunc("/pix/", pix)
http.HandleFunc("/img/", img)
http.HandleFunc("/red/", img)
http.HandleFunc("/", img)
http.ListenAndServe(":8080", nil)
}
答案2
得分: 9
func getSize(stream io.Reader) int {
buf := new(bytes.Buffer)
buf.ReadFrom(stream)
return buf.Len()
}
英文:
func getSize(stream io.Reader) int {
buf := new(bytes.Buffer)
buf.ReadFrom(stream)
return buf.Len()
}
答案3
得分: 3
应用程序不需要设置内容长度。如果应用程序没有指定内容长度,则 net/http 服务器将对 HTTP/1.1 客户端使用分块编码。对于 HTTP/1.0 客户端,net/http 服务器在写入响应后关闭连接。有一些边缘情况对于本讨论并不重要。重要的是 net/http 服务器可以在不知道内容长度的情况下写入响应。
使用以下代码来写入响应:
func img(w http.ResponseWriter, r *http.Request) {
expiration := time.Now().Add(365 * 24 * time.Hour)
cookie := http.Cookie{Name: "csrftoken", Value: "abcd", Expires: expiration, HttpOnly: false}
http.SetCookie(w, &cookie)
img := bytes.NewBufferString("iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAIAAACRXR/mAAADMUlEQVRYw+2YTUgUYRjHZzOJIoNA+rrUyYNIRQgRHaLo4qFDBEGeunSxS9TFU0QEnhIh6IvokrUzO2uamRmbG6XmR/mVaKZpZVbYvvO143zszsxOz+yahNm+785sITEP72F3Z+adH8/zf5+PpagwtxKXj+Vj+Vg+lo/lY+W+WI4KpddKwWIQFUSF97nNLcLGZt75SiOHchEXfskDVmYjlowpiEoei3UT2ljcFJOpOd169C1Z2SuvgsdpB7cgzB16EV/byGM2xDIVPxQujKmBDF/2m2l0vFvmEin7N2v8kiiPiOeGlGHRvP1RdxA9eYtGR7pk2Pf6lI7RCoP2RaWkZWe3fsFc18hvesAHPGEFUc24ltnx3kyiCJwfRMs6dTXLdSIjO9Osal18qzKfE5V9coDxhlU7qS3uOyiaB55JDtkS2TKoLCLaOLPS4b02pQdCHiUfRKf653/d2kjZN6f10jYxI2EnrGk5H+2WsVi6ZZ8fVSmGQKaYyyFuR6ugmUtVrJo2C7HokeGq8447sYpOPBbo3XFzKC95626sZlz905sUM9XLGbXvtKtTOhZrQDApkhNNkiAOPo/viojh2YSZsj1aF2eQ5n2stuomNQjiiGQanrFufdCXP8gu8tbhjridJ6saVPKExXJrwlwfb3pnAg2Ut0tEBZFI8gza81Tik15DCDIoINQ7aQdBo90RMfrdwNaWLFY9opJGkBQrhCA/HXspQ8W1XHkN6vfWFiGH9ouwhdpJUFuy2JX3eg6uyqENpNHZYcUd02jcLMI2WO67UwZVv1G1HLMq3L83KuEbLPdY7IL2L42p0MMQiuzkq/ncwucOi6qPbWkWoPfCUsENpweUnP1EmE4XGhgagT72RyXolkSCHBbTU3By3fgJj8VyJW3CmSHl8oTWMJuYUUizVvtcsuyJ6J4J663CMLevXar/lJgnKNSgbphzKjriTn5i0F8eX9ODXnEzf6JHvjGtv+aNGdWCOEKnJRmpr5oFVQV8WTWglIKHMlPhv5uqQ1xGYfB5fRMPo+n2VmFbi7ChiS9oWBhZvXrI01TNLg7yPxt51v9rxMfysXwsH8vH+g+wfgDUr+5LcyNV4AAAAABJRU5ErkJggg==")
dec := base64.NewDecoder(base64.StdEncoding, img)
w.Header().Set("Content-Type", "image/jpeg")
io.Copy(w, dec)
}
你可以通过使用 strings.NewReader 替代 bytes.NewBufferString 来减少内存分配:
img := strings.NewReader("iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAIAAACRXR/mAAADMUlEQVRYw+2YTUgUYRjHZzOJIoNA+rrUyYNIRQgRHaLo4qFDBEGeunSxS9TFU0QEnhIh6IvokrUzO2uamRmbG6XmR/mVaKZpZVbYvvO143zszsxOz+yahNm+785sITEP72F3Z+adH8/zf5+PpagwtxKXj+Vj+Vg+lo/lY+W+WI4KpddKwWIQFUSF97nNLcLGZt75SiOHchEXfskDVmYjlowpiEoei3UT2ljcFJOpOd169C1Z2SuvgsdpB7cgzB16EV/byGM2xDIVPxQujKmBDF/2m2l0vFvmEin7N2v8kiiPiOeGlGHRvP1RdxA9eYtGR7pk2Pf6lI7RCoP2RaWkZWe3fsFc18hvesAHPGEFUc24ltnx3kyiCJwfRMs6dTXLdSIjO9Osal18qzKfE5V9coDxhlU7qS3uOyiaB55JDtkS2TKoLCLaOLPS4b02pQdCHiUfRKf653/d2kjZN6f10jYxI2EnrGk5H+2WsVi6ZZ8fVSmGQKaYyyFuR6ugmUtVrJo2C7HokeGq8447sYpOPBbo3XFzKC95626sZlz905sUM9XLGbXvtKtTOhZrQDApkhNNkiAOPo/viojh2YSZsj1aF2eQ5n2stuomNQjiiGQanrFufdCXP8gu8tbhjridJ6saVPKExXJrwlwfb3pnAg2Ut0tEBZFI8gza81Tik15DCDIoINQ7aQdBo90RMfrdwNaWLFY9opJGkBQrhCA/HXspQ8W1XHkN6vfWFiGH9ouwhdpJUFuy2JX3eg6uyqENpNHZYcUd02jcLMI2WO67UwZVv1G1HLMq3L83KuEbLPdY7IL2L42p0MMQiuzkq/ncwucOi6qPbWkWoPfCUsENpweUnP1EmE4XGhgagT72RyXolkSCHBbTU3By3fgJj8VyJW3CmSHl8oTWMJuYUUizVvtcsuyJ6J4J663CMLevXar/lJgnKNSgbphzKjriTn5i0F8eX9ODXnEzf6JHvjGtv+aNGdWCOEKnJRmpr5oFVQV8WTWglIKHMlPhv5uqQ1xGYfB5fRMPo+n2VmFbi7ChiS9oWBhZvXrI01TNLg7yPxt51v9rxMfysXwsH8vH+g+wfgDUr+5LcyNV4AAAAABJRU5ErkJggg==")
如果应用程序必须避免使用分块响应,则应用程序必须设置 Content-Length 头。将图像解码为缓冲区,获取该缓冲区的长度,并在写入正文之前设置头:
func img(w http.ResponseWriter, r *http.Request) {
expiration := time.Now().Add(365 * 24 * time.Hour)
cookie := http.Cookie{Name: "csrftoken", Value: "abcd", Expires: expiration, HttpOnly: false}
http.SetCookie(w, &cookie)
p, err := base64.StdEncoding.DecodeString("iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAIAAACRXR/mAAADMUlEQVRYw+2YTUgUYRjHZzOJIoNA+rrUyYNIRQgRHaLo4qFDBEGeunSxS9TFU0QEnhIh6IvokrUzO2uamRmbG6XmR/mVaKZpZVbYvvO143zszsxOz+yahNm+785sITEP72F3Z+adH8/zf5+PpagwtxKXj+Vj+Vg+lo/lY+W+WI4KpddKwWIQFUSF97nNLcLGZt75SiOHchEXfskDVmYjlowpiEoei3UT2ljcFJOpOd169C1Z2SuvgsdpB7cgzB16EV/byGM2xDIVPxQujKmBDF/2m2l0vFvmEin7N2v8kiiPiOeGlGHRvP1RdxA9eYtGR7pk2Pf6lI7RCoP2RaWkZWe3fsFc18hvesAHPGEFUc24ltnx3kyiCJwfRMs6dTXLdSIjO9Osal18qzKfE5V9coDxhlU7qS3uOyiaB55JDtkS2TKoLCLaOLPS4b02pQdCHiUfRKf653/d2kjZN6f10jYxI2EnrGk5H+2WsVi6ZZ8fVSmGQKaYyyFuR6ugmUtVrJo2C7HokeGq8447sYpOPBbo3XFzKC95626sZlz905sUM9XLGbXvtKtTOhZrQDApkhNNkiAOPo/viojh2YSZsj1aF2eQ5n2stuomNQjiiGQanrFufdCXP8gu8tbhjridJ6saVPKExXJrwlwfb3pnAg2Ut0tEBZFI8gza81Tik15DCDIoINQ7aQdBo90RMfrdwNaWLFY9opJGkBQrhCA/HXspQ8W1XHkN6vfWFiGH9ouwhdpJUFuy2JX3eg6uyqENpNHZYcUd02jcLMI2WO67UwZVv1G1HLMq3L83KuEbLPdY7IL2L42p0MMQiuzkq/ncwucOi6qPbWkWoPfCUsENpweUnP1EmE4XGhgagT72RyXolkSCHBbTU3By3fgJj8VyJW3CmSHl8oTWMJuYUUizVvtcsuyJ6J4J663CMLevXar/lJgnKNSgbphzKjriTn5i0F8eX9ODXnEzf6JHvjGtv+aNGdWCOEKnJRmpr5oFVQV8WTWglIKHMlPhv5uqQ1xGYfB5fRMPo+n2VmFbi7ChiS9oWBhZvXrI01TNLg7yPxt51v9rxMfysXwsH8vH+g+wfgDUr+5LcyNV4AAAAABJRU5ErkJggg==")
if err != nil {
http.Error(w, "internal error", 500)
return
}
w.Header().Set("Content-Type", "image/jpeg")
w.Header().Set("Content-Length", strconv.Itoa(len(p)))
w.Write(p)
}
英文:
The application does not need to set the content length. If the application does not specify the content length, then net/http server uses chunked encoding for HTTP/1.1 clients. For HTTP/1.0 clients, the net/http server closes the connection after writing the response. There are some edge cases that are not important for this discussion. What is important is that the net/http server can write the response without knowing the content length.
Use the following code to write the response:
func img(w http.ResponseWriter, r *http.Request) {
expiration := time.Now().Add(365 * 24 * time.Hour)
cookie := http.Cookie{Name: "csrftoken",Value:"abcd",Expires:expiration,HttpOnly: false}
http.SetCookie(w, &cookie)
img := bytes.NewBufferString("iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAIAAACRXR/mAAADMUlEQVRYw+2YTUgUYRjHZzOJIoNA+rrUyYNIRQgRHaLo4qFDBEGeunSxS9TFU0QEnhIh6IvokrUzO2uamRmbG6XmR/mVaKZpZVbYvvO143zszsxOz+yahNm+785sITEP72F3Z+adH8/zf5+PpagwtxKXj+Vj+Vg+lo/lY+W+WI4KpddKwWIQFUSF97nNLcLGZt75SiOHchEXfskDVmYjlowpiEoei3UT2ljcFJOpOd169C1Z2SuvgsdpB7cgzB16EV/byGM2xDIVPxQujKmBDF/2m2l0vFvmEin7N2v8kiiPiOeGlGHRvP1RdxA9eYtGR7pk2Pf6lI7RCoP2RaWkZWe3fsFc18hvesAHPGEFUc24ltnx3kyiCJwfRMs6dTXLdSIjO9Osal18qzKfE5V9coDxhlU7qS3uOyiaB55JDtkS2TKoLCLaOLPS4b02pQdCHiUfRKf653/d2kjZN6f10jYxI2EnrGk5H+2WsVi6ZZ8fVSmGQKaYyyFuR6ugmUtVrJo2C7HokeGq8447sYpOPBbo3XFzKC95626sZlz905sUM9XLGbXvtKtTOhZrQDApkhNNkiAOPo/viojh2YSZsj1aF2eQ5n2stuomNQjiiGQanrFufdCXP8gu8tbhjridJ6saVPKExXJrwlwfb3pnAg2Ut0tEBZFI8gza81Tik15DCDIoINQ7aQdBo90RMfrdwNaWLFY9opJGkBQrhCA/HXspQ8W1XHkN6vfWFiGH9ouwhdpJUFuy2JX3eg6uyqENpNHZYcUd02jcLMI2WO67UwZVv1G1HLMq3L83KuEbLPdY7IL2L42p0MMQiuzkq/ncwucOi6qPbWkWoPfCUsENpweUnP1EmE4XGhgagT72RyXolkSCHBbTU3By3fgJj8VyJW3CmSHl8oTWMJuYUUizVvtcsuyJ6J4J663CMLevXar/lJgnKNSgbphzKjriTn5i0F8eX9ODXnEzf6JHvjGtv+aNGdWCOEKnJRmpr5oFVQV8WTWglIKHMlPhv5uqQ1xGYfB5fRMPo+n2VmFbi7ChiS9oWBhZvXrI01TNLg7yPxt51v9rxMfysXwsH8vH+g+wfgDUr+5LcyNV4AAAAABJRU5ErkJggg==")
dec := base64.NewDecoder(base64.StdEncoding, img)
w.Header().Set("Content-Type", "image/jpeg")
io.Copy(w, dec)
}
You can reduce memory allocations by using strings.NewReader instead of bytes.NewBufferString:
img := strings.NewReader("iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAIAAACRXR/mAAADMUlEQVRYw+2YTUgUYRjHZzOJIoNA+rrUyYNIRQgRHaLo4qFDBEGeunSxS9TFU0QEnhIh6IvokrUzO2uamRmbG6XmR/mVaKZpZVbYvvO143zszsxOz+yahNm+785sITEP72F3Z+adH8/zf5+PpagwtxKXj+Vj+Vg+lo/lY+W+WI4KpddKwWIQFUSF97nNLcLGZt75SiOHchEXfskDVmYjlowpiEoei3UT2ljcFJOpOd169C1Z2SuvgsdpB7cgzB16EV/byGM2xDIVPxQujKmBDF/2m2l0vFvmEin7N2v8kiiPiOeGlGHRvP1RdxA9eYtGR7pk2Pf6lI7RCoP2RaWkZWe3fsFc18hvesAHPGEFUc24ltnx3kyiCJwfRMs6dTXLdSIjO9Osal18qzKfE5V9coDxhlU7qS3uOyiaB55JDtkS2TKoLCLaOLPS4b02pQdCHiUfRKf653/d2kjZN6f10jYxI2EnrGk5H+2WsVi6ZZ8fVSmGQKaYyyFuR6ugmUtVrJo2C7HokeGq8447sYpOPBbo3XFzKC95626sZlz905sUM9XLGbXvtKtTOhZrQDApkhNNkiAOPo/viojh2YSZsj1aF2eQ5n2stuomNQjiiGQanrFufdCXP8gu8tbhjridJ6saVPKExXJrwlwfb3pnAg2Ut0tEBZFI8gza81Tik15DCDIoINQ7aQdBo90RMfrdwNaWLFY9opJGkBQrhCA/HXspQ8W1XHkN6vfWFiGH9ouwhdpJUFuy2JX3eg6uyqENpNHZYcUd02jcLMI2WO67UwZVv1G1HLMq3L83KuEbLPdY7IL2L42p0MMQiuzkq/ncwucOi6qPbWkWoPfCUsENpweUnP1EmE4XGhgagT72RyXolkSCHBbTU3By3fgJj8VyJW3CmSHl8oTWMJuYUUizVvtcsuyJ6J4J663CMLevXar/lJgnKNSgbphzKjriTn5i0F8eX9ODXnEzf6JHvjGtv+aNGdWCOEKnJRmpr5oFVQV8WTWglIKHMlPhv5uqQ1xGYfB5fRMPo+n2VmFbi7ChiS9oWBhZvXrI01TNLg7yPxt51v9rxMfysXwsH8vH+g+wfgDUr+5LcyNV4AAAAABJRU5ErkJggg==")
If the application must avoid chunked responses, then the application must set the Content-Length header. Decode the image to a buffer, get the length of that buffer and set the header before writing the body:
func img(w http.ResponseWriter, r *http.Request) {
expiration := time.Now().Add(365 * 24 * time.Hour)
cookie := http.Cookie{Name: "csrftoken",Value:"abcd",Expires:expiration,HttpOnly: false}
http.SetCookie(w, &cookie)
p, err := base64.StdEncoding.DecodeString("iVBORw0KGgoAAAANSUhEUgAAADIAAAAyCAIAAACRXR/mAAADMUlEQVRYw+2YTUgUYRjHZzOJIoNA+rrUyYNIRQgRHaLo4qFDBEGeunSxS9TFU0QEnhIh6IvokrUzO2uamRmbG6XmR/mVaKZpZVbYvvO143zszsxOz+yahNm+785sITEP72F3Z+adH8/zf5+PpagwtxKXj+Vj+Vg+lo/lY+W+WI4KpddKwWIQFUSF97nNLcLGZt75SiOHchEXfskDVmYjlowpiEoei3UT2ljcFJOpOd169C1Z2SuvgsdpB7cgzB16EV/byGM2xDIVPxQujKmBDF/2m2l0vFvmEin7N2v8kiiPiOeGlGHRvP1RdxA9eYtGR7pk2Pf6lI7RCoP2RaWkZWe3fsFc18hvesAHPGEFUc24ltnx3kyiCJwfRMs6dTXLdSIjO9Osal18qzKfE5V9coDxhlU7qS3uOyiaB55JDtkS2TKoLCLaOLPS4b02pQdCHiUfRKf653/d2kjZN6f10jYxI2EnrGk5H+2WsVi6ZZ8fVSmGQKaYyyFuR6ugmUtVrJo2C7HokeGq8447sYpOPBbo3XFzKC95626sZlz905sUM9XLGbXvtKtTOhZrQDApkhNNkiAOPo/viojh2YSZsj1aF2eQ5n2stuomNQjiiGQanrFufdCXP8gu8tbhjridJ6saVPKExXJrwlwfb3pnAg2Ut0tEBZFI8gza81Tik15DCDIoINQ7aQdBo90RMfrdwNaWLFY9opJGkBQrhCA/HXspQ8W1XHkN6vfWFiGH9ouwhdpJUFuy2JX3eg6uyqENpNHZYcUd02jcLMI2WO67UwZVv1G1HLMq3L83KuEbLPdY7IL2L42p0MMQiuzkq/ncwucOi6qPbWkWoPfCUsENpweUnP1EmE4XGhgagT72RyXolkSCHBbTU3By3fgJj8VyJW3CmSHl8oTWMJuYUUizVvtcsuyJ6J4J663CMLevXar/lJgnKNSgbphzKjriTn5i0F8eX9ODXnEzf6JHvjGtv+aNGdWCOEKnJRmpr5oFVQV8WTWglIKHMlPhv5uqQ1xGYfB5fRMPo+n2VmFbi7ChiS9oWBhZvXrI01TNLg7yPxt51v9rxMfysXwsH8vH+g+wfgDUr+5LcyNV4AAAAABJRU5ErkJggg==")
if err != nil {
http.Error(w, "internal error", 500)
return
}
w.Header().Set("Content-Type", "image/jpeg")
w.Header().Set("Content-Length", strconv.Itoa(len(p)))
w.Write(p)
}
答案4
得分: 0
如果你的io.Reader
也是io.Seeker
(例如当你想将文件返回给用户时),你可以采取以下方法,避免将文件缓存到内存中:
if s, ok := reader.(io.Seeker); ok {
if size, err := s.Seek(0, io.SeekEnd); err == nil {
// 将文件指针定位到文件开头,以便正确地提供文件
if _, err = s.Seek(0, io.SeekStart) {
w.Header().Set("Content-Length", strconv.Itoa(size))
}
// 错误处理
}
// 错误处理
}
// 继续提供文件
英文:
If your io.Reader
is also io.Seeker
(for example when you want to serve a file back to the user) you can do the following and avoid caching the file into memory:
if s, ok := reader.(io.Seeker); ok {
if size, err := s.Seek(0, io.SeekEnd); err == nil {
// seek back to the start of file so that it can be served properly
if _, err = s.Seek(0, io.SeekStart) {
w.Header().Set("Content-Length", strconv.Itoa(size))
}
// error handeling
}
// error handeling
}
// continue serving the file
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论