英文:
What is the difference between writing html through response writer and directly serving file in golang?
问题
我是新手学习golang,我正在尝试创建一个服务器,用于获取文件列表并创建一个HTML文件,并将其写入响应中。
我已经创建了文件的链接,以便在点击链接时下载文件。
但是,实际上下载的是HTML文件,而不是文件本身。
以下是我的代码:
package main
import (
"fmt"
"io/ioutil"
"net/http"
"io"
)
func getFile(res http.ResponseWriter, req *http.Request) {
files, _ := ioutil.ReadDir("./publicFolder/")
res.Header().Set("Content-Type", "text/html; charset=utf-8")
myHtml := `
<!DOCTYPE html>
<html>
<head>
<title>Home Network</title>
</head>
<body>
<ul>`
for _, f := range files {
fmt.Println(f.Name())
myHtml += (`
<a href="./publicFolder/` + f.Name() + `" download="` + f.Name() + `">` + f.Name() + `</a>`)
}
myHtml += (
`
</ul>
</body>
</html>
`)
io.WriteString(res, myHtml)
}
func main() {
http.HandleFunc("/getFile/", getFile)
http.ListenAndServe(":8008", nil)
}
我在<a>
标签中添加了download
属性,但实际上下载的是HTML文件,而不是文件本身。
我尝试创建一个HTML文件并运行它,这种情况下文件可以被正确下载。
以下是我用于测试的HTML文件的内容:
<html>
<head>
</head>
<body>
<ul>
<li><a href="./publicFolder/doc.txt" download="doc.txt">file1</a></li>
</ul>
</body>
</html>
编辑
使用golang服务器下载时,doc.txt
文件的内容如下:
<html>
<head>
<title>
Home Network
</title>
</head>
<body>
<ul>
<li>
<a href="./publicFolder/GAMES.cpp" download="GAMES.cpp">GAMES.cpp</a>
</li>
<li>
<a href="./publicFolder/doc.txt" download="doc.txt">doc.txt</a>
</li>
<li>
<a href="./publicFolder/erlang" download="erlang">erlang</a>
</li>
</ul>
</body>
</html>
从HTML文件下载时,doc.txt
文件的内容是实际内容:
this is a test file doct.txt
编辑
我已经添加了以下的FileServer
:
http.Handle("/getFile/publicFolder/", http.StripPrefix("/getFile/publicFolder/", http.FileServer(http.Dir("/publicFolder"))))
英文:
I am new to golang and i am trying to make a server which will fetch the list of files and create an html and write it to the response
i have created links of the file so that when it is clicked , then the file is downloaded
But this is not happening , instead the html is being downloaded instead of file
here is what i am doing
package main
import (
"fmt"
"io/ioutil"
"net/http"
"io"
)
func getFile(res http.ResponseWriter, req *http.Request) {
files, _ := ioutil.ReadDir("./publicFolder/")
res.Header().Set("Content-Type", "text/html; charset=utf-8")
myHtml := `
<!DOCTYPE html>
<html>
<head>
<title>Home Network</title>
</head>
<body>
<ul>`
for _, f := range files {
fmt.Println(f.Name())
myHtml += (`
<a href="./publicFolder/` + f.Name() + `" download="`+f.Name()+`" >` + f.Name() + `</a>`)
}
myHtml += (
`
</ul>
</body>
</html>
`)
io.WriteString(res, myHtml)
}
func main() {
http.HandleFunc("/getFile/", getFile)
http.ListenAndServe(":8008", nil)
}
i have added download attribute to the html in <a> tag
But the html is being downloaded instead of file
i tried creating an html file and running it , in that case the file is being downloaded
here is the html which i created to test
<html>
<head>
</head>
<body>
<ul>
<li><a href="./publicFolder/doc.txt" download="doc.txt">file1</a></li>
</ul>
</body>
</html>
EDIT
the content of doc.txt when downloading using the golang server
<html>
<head>
<title>
Home Network
</title>
</head>
<body>
<ul>
<li>
<a href="./publicFolder/GAMES.cpp" download="GAMES.cpp">GAMES.cpp</a>
</li>
<li>
<a href="./publicFolder/doc.txt" download="doc.txt">doc.txt</a>
</li>
<li>
<a href="./publicFolder/erlang" download="erlang">erlang</a>
</li>
</ul>
</body>
</html>
Content of doc.txt when downloading from html file(and this is the actual content )
this is a test file doct.txt
EDIT
i have added this FileServer
http.Handle("/getFile/publicFolder/", http.StripPrefix("/getFile/publicFolder/", http.FileServer(http.Dir("/publicFolder"))))
答案1
得分: 2
当你在浏览器中打开一个本地HTML文件时,浏览器会从你的磁盘上读取该HTML文件。你会看到一个URL和协议,类似于file:///home/bob/test.html
。在这种情况下,你的Go Web服务器不会被调用(它被排除在"循环"之外)。由于你在<a>
标签的href
属性中使用的是相对路径,它们也会指向本地文件(file:///
协议),所以浏览器也会直接读取链接的文件,"绕过"你的Go Web服务器。
如果你从Go中提供HTML(就像你的示例中的HTTP处理程序),然后从浏览器访问它,那么浏览器不会读取文件,它会根据你的链接<a>
执行另一个HTTP GET
请求。你的Go服务器必须读取并发送它。
再次,查看这个答案,了解如何从Go中提供文件:https://stackoverflow.com/questions/28899675/include-js-file-in-go-template/28899786#28899786
英文:
When you open a local HTML file in your browser, then the browser will read the HTML file locally, from your disk. You will see a URL and protocol something like file:///home/bob/test.html
. In this case your Go web server is not called (it's excluded from the "loop"). Since you use relative paths in the href
attributes of your <a>
tags, they will also point to local files (file:///
protocol), so the browser will also read the linked files directly, "avoiding" your Go web server.
If you serve the HTML from Go (HTTP handler as in your example), and you access it from the browser, then the browser will not read the file, it will perform another HTTP GET
as your link <a>
dictates. Your Go server has to read it and send it.
Again, check out this answer how you can serve files from Go: https://stackoverflow.com/questions/28899675/include-js-file-in-go-template/28899786#28899786
答案2
得分: 1
icza的答案是正确的,让我解释一些事情。
在golang中,通过响应写入器(response writer)编写HTML和直接提供文件有什么区别?
没有区别。无论哪种方式,你都将写入一个io.Writer
。
我已经创建了文件的链接,以便在点击链接时下载文件
但实际上并没有发生这种情况,而是下载了HTML文件而不是文件本身
大致上是这样的:
- 你在浏览器中打开
http://localhost:8008/getFile/
。 - 浏览器向
http://localhost:8008/getFile/
发起HTTP请求。 - 你的Go服务器接收到请求。由于请求以
/getFile/
开头,它运行getFile
处理程序。 getFile
处理程序将HTML写回浏览器。- 浏览器接收到HTML(文件列表)。
- 你点击
doc.txt
的链接。 - 浏览器向
http://localhost:8008/getFile/publicFolder/doc.txt
发起HTTP请求。 - (与步骤3相同)
- (与步骤4相同)
- (与步骤5相同)
你从来没有告诉你的Go服务器如何发送这些文件。你唯一告诉它要做的事情是:
- 如果收到一个请求,并且其路径以
/getFile/
开头,则回复这个HTML。
这是它唯一要做的事情,而且它做得很好。
英文:
While icza's answer is right, let me explain some things.
> What is the difference between writing html through response writer and directly serving file in golang?
None. You'll be writing to an io.Writer
either way.
> i have created links of the file so that when it is clicked , then the file is downloaded
>
> But this is not happening , instead the html is being downloaded instead of file
This is roughly what is happening under the hood:
- You open
http://localhost:8008/getFile/
in your browser. - Your browser makes an HTTP request to
http://localhost:8008/getFile/
. - Your Go server receives the request. Since it begins with
/getFile/
, it runs thegetFile
handler. - The
getFile
handler writes HTML back to the browser. - The browser receives that HTML (the list of files).
- You click in the link for
doc.txt
. - The browser makes an HTTP request to
http://localhost:8008/getFile/publicFolder/doc.txt
- (Same as step 3)
- (Same as step 4)
- (Same as step 5)
You're never telling your Go server how to send those files. The only thing you're telling it to do is:
- If you get a request, and its path starts with
/getFile/
, reply with this HTML.
That's the only thing it's doing, and it's doing it fine.
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论