What is the difference between writing html through response writer and directly serving file in golang?

huangapple go评论71阅读模式
英文:

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 (
    &quot;fmt&quot;
    &quot;io/ioutil&quot;
    &quot;net/http&quot;
    &quot;io&quot;
)

func getFile(res http.ResponseWriter, req *http.Request) {

    files, _ := ioutil.ReadDir(&quot;./publicFolder/&quot;)
    res.Header().Set(&quot;Content-Type&quot;, &quot;text/html; charset=utf-8&quot;)

 	myHtml := `
           &lt;!DOCTYPE html&gt;
           &lt;html&gt;
	       &lt;head&gt;
	         &lt;title&gt;Home Network&lt;/title&gt;
	       &lt;/head&gt;
	       &lt;body&gt;
		      &lt;ul&gt;`
   	for _, f := range files	{
	fmt.Println(f.Name())
	myHtml += (`
		&lt;a href=&quot;./publicFolder/` + f.Name() + `&quot; download=&quot;`+f.Name()+`&quot; &gt;` + f.Name() + `&lt;/a&gt;`)

    }
    myHtml += (
	`
	&lt;/ul&gt;
	&lt;/body&gt;
	&lt;/html&gt;
	`)	
    io.WriteString(res, myHtml)
}

func main() {
    http.HandleFunc(&quot;/getFile/&quot;, getFile)
 	http.ListenAndServe(&quot;:8008&quot;, 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

&lt;html&gt;
    &lt;head&gt;
	&lt;/head&gt;
    &lt;body&gt;
	   &lt;ul&gt;
		    &lt;li&gt;&lt;a href=&quot;./publicFolder/doc.txt&quot; download=&quot;doc.txt&quot;&gt;file1&lt;/a&gt;&lt;/li&gt;
	    &lt;/ul&gt;
    &lt;/body&gt;
&lt;/html&gt;

EDIT

the content of doc.txt when downloading using the golang server

&lt;html&gt;
	&lt;head&gt;
	&lt;title&gt;
		Home Network
	&lt;/title&gt;
	&lt;/head&gt;
	&lt;body&gt;
		&lt;ul&gt;
		&lt;li&gt;
		  &lt;a href=&quot;./publicFolder/GAMES.cpp&quot; download=&quot;GAMES.cpp&quot;&gt;GAMES.cpp&lt;/a&gt;
		&lt;/li&gt;
		&lt;li&gt;
		  &lt;a href=&quot;./publicFolder/doc.txt&quot; download=&quot;doc.txt&quot;&gt;doc.txt&lt;/a&gt;
		&lt;/li&gt;
		&lt;li&gt;
		  &lt;a href=&quot;./publicFolder/erlang&quot; download=&quot;erlang&quot;&gt;erlang&lt;/a&gt;
		&lt;/li&gt;
	&lt;/ul&gt;
	&lt;/body&gt;
	&lt;/html&gt;

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(&quot;/getFile/publicFolder/&quot;, http.StripPrefix(&quot;/getFile/publicFolder/&quot;, http.FileServer(http.Dir(&quot;/publicFolder&quot;))))

答案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 &lt;a&gt; 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 &lt;a&gt; 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文件而不是文件本身

大致上是这样的:

  1. 你在浏览器中打开http://localhost:8008/getFile/
  2. 浏览器向http://localhost:8008/getFile/发起HTTP请求。
  3. 你的Go服务器接收到请求。由于请求以/getFile/开头,它运行getFile处理程序。
  4. getFile处理程序将HTML写回浏览器。
  5. 浏览器接收到HTML(文件列表)。
  6. 你点击doc.txt的链接。
  7. 浏览器向http://localhost:8008/getFile/publicFolder/doc.txt发起HTTP请求。
  8. (与步骤3相同)
  9. (与步骤4相同)
  10. (与步骤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:

  1. You open http://localhost:8008/getFile/ in your browser.
  2. Your browser makes an HTTP request to http://localhost:8008/getFile/.
  3. Your Go server receives the request. Since it begins with /getFile/, it runs the getFile handler.
  4. The getFile handler writes HTML back to the browser.
  5. The browser receives that HTML (the list of files).
  6. You click in the link for doc.txt.
  7. The browser makes an HTTP request to http://localhost:8008/getFile/publicFolder/doc.txt
  8. (Same as step 3)
  9. (Same as step 4)
  10. (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.

huangapple
  • 本文由 发表于 2017年1月11日 21:58:07
  • 转载请务必保留本文链接:https://go.coder-hub.com/41592848.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定