Go语言使用net/http实现简单登录验证和文件上传功能

这篇具有很好参考价值的文章主要介绍了Go语言使用net/http实现简单登录验证和文件上传功能。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

     最近再看Go语言web编程,go语言搭建Web服务器,既可以用go原生的net/http包,也可以用gin/fasthttp/fiber等这些Web框架。本博客使用net/http模块编写了一个简单的登录验证和文件上传的功能,在此做个简单记录。

目录

1.文件目录结构

2.编译运行

3.用户登录

 4.文件上传

5.mime/multipart模拟form表单上传文件


代码如下:

package main

import (
	"fmt"
	"html/template"
	"io"
	"log"
	"net/http"
	"os"
)

/*
go运行方式:
(1)解释运行
go run main.go

(2)编译运行
--使用默认名
go build main.go
./main
--指定可执行程序名
go build -o test main.go
./test
*/

// http://127.0.0.1:8181/login
func login(w http.ResponseWriter, r *http.Request) {
	fmt.Println("method", r.Method)
	if r.Method == "GET" {
		t, _ := template.ParseFiles("login.html")
		t.Execute(w, nil)
		/*
			//字符串拼装表单
				html := `<html>
					<head>
					<title>上传文件</title>
					</head>
					<body>
					<form enctype="multipart/form-data" action="http://localhost:8181/upload" method="post">
						<input type="file" name="uploadfile" />
						<input type="hidden" name="token" value="{
						{.}}" />
						<input type="submit" value="upload" />
					</form>
					</body>
					</html>`
				crutime := time.Now().Unix()
				h := md5.New()
				io.WriteString(h, strconv.FormatInt(crutime, 10))
				token := fmt.Sprintf("%x", h.Sum(nil))
				t := template.Must(template.New("test").Parse(html))
				t.Execute(w, token)
		*/
	} else {
		r.ParseForm()
		fmt.Println("username", r.Form["username"])
		fmt.Println("password", r.Form["password"])
		fmt.Fprintf(w, "登录成功")
	}
}

// http://127.0.0.1:8181/upload
func upload(writer http.ResponseWriter, r *http.Request) {
	//表示maxMemory,调用ParseMultipart后,上传的文件存储在maxMemory大小的内存中,
	//如果大小超过maxMemory,剩下部分存储在系统的临时文件中
	r.ParseMultipartForm(32 << 10)
	//根据input中的name="uploadfile"来获得上传的文件句柄
	file, header, err := r.FormFile("uploadfile")
	if err != nil {
		fmt.Fprintf(writer, "上传出错")
		fmt.Println(err)
		return
	}
	defer file.Close()
	/*
		fmt.Printf("Uploaded File: %+v\n", header.Filename)
		fmt.Printf("File Size: %+v\n", header.Size)
				// 注意此处的header.Header是textproto.MIMEHeader类型 ( map[string][]string )
		fmt.Printf("MIME Type: %+v\n", header.Header.Get("Content-Type"))
		// 将文件保存到服务器指定的目录(* 用来随机数的占位符)
		tempFile, err := ioutil.TempFile("uploads", "*"+header.Filename)
	*/
	fmt.Println("handler.Filename", header.Filename)
	f, err := os.OpenFile("./filedir/"+header.Filename, os.O_WRONLY|os.O_CREATE, 0666)
	if err != nil {
		fmt.Println(err)
		fmt.Fprintf(writer, "上传出错")
		return
	}
	defer f.Close()
	io.Copy(f, file)
	fmt.Fprintf(writer, "上传成功")
}

func common_handle() {
	http.HandleFunc("/", func(w http.ResponseWriter, r *http.Request) {
		w.Write([]byte("Hello world !"))
	})
	http.HandleFunc("/login", login)
	http.HandleFunc("/upload", upload)
}

func main1() {
	common_handle()
	//监听8181端口
	err := http.ListenAndServe(":8181", nil)
	if err != nil {
		log.Fatal("err:", err)
	}
}

// 声明helloHandler
type helloHandler struct{}

// 定义helloHandler
func (m11111 *helloHandler) ServeHTTP(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("Hello world, this is my first golang programe !"))
}

func welcome(w http.ResponseWriter, r *http.Request) {
	w.Write([]byte("Welcome to golang family !"))
}

func main2() {
	a := helloHandler{}

	//使用http.Handle
	http.Handle("/hello", &a)
	http.Handle("/welcome", http.HandlerFunc(welcome))

	common_handle()

	server := http.Server{
		Addr:    "127.0.0.1:8181",
		Handler: nil, // 对应DefaultServeMux路由
	}
	server.ListenAndServe()
}

func main() {
	main2()
}

login.html

<!DOCTYPE html>
<html lang="en">
	<head>
		<meta charset="UTF-8"/>
		<title>欢迎进入首页</title>
	</head>
	<body>
		<h3>登录测试</h3>
		<hr/>

		<form action="http://localhost:8181/login" method="post">
			<table border=0 title="测试">
				<tr>
					<td>用户名:</td>
					<td><input type="text" name="username"></td>
				</tr>
				<tr>
					<td>密码:</td>
					<td><input type="password" name="password"></td>
				</tr>
				<tr>
					<td colspan=2>
						<input type="reset" />
						<input type="submit" value="登录" />
					</td>
				</tr>
			</table>
		</form>
		<br>
		<h3>文件上传测试</h3>
		<hr/>
		<form action="http://localhost:8181/upload" method="post" enctype="multipart/form-data">
			<input type="file" name="uploadfile"/>
			<input type="submit" value="upload">
		</form>
	</body>
</html>

1.文件目录结构

Go语言使用net/http实现简单登录验证和文件上传功能

2.编译运行

 Go语言使用net/http实现简单登录验证和文件上传功能

3.用户登录

http://127.0.0.1:8181/login

Go语言使用net/http实现简单登录验证和文件上传功能

Go语言使用net/http实现简单登录验证和文件上传功能

Go语言使用net/http实现简单登录验证和文件上传功能

Go语言使用net/http实现简单登录验证和文件上传功能

 4.文件上传

Go语言使用net/http实现简单登录验证和文件上传功能

Go语言使用net/http实现简单登录验证和文件上传功能

 Go语言使用net/http实现简单登录验证和文件上传功能

Go语言使用net/http实现简单登录验证和文件上传功能

5.mime/multipart模拟form表单上传文件

       使用mime/multipart包,可以将multipart/form-data数据解析为一组文件和表单字段,或者使用multipart.Writer将文件和表单字段写入HTTP请求体中。

       以下例子中首先打开要上传的文件,然后创建一个multipart.Writer,用于构造multipart/form-data格式的请求体。我们使用CreateFormFile方法创建一个multipart.Part,用于表示文件字段,将文件内容复制到该Part中。我们还使用WriteField方法添加其他表单字段。然后,我们关闭multipart.Writer,以便写入Content-Type和boundary,并使用NewRequest方法创建一个HTTP请求。我们将Content-Type设置为multipart/form-data,并使用默认的HTTP客户端发送请求。最后,我们读取并处理响应。

关于什么是multipart/form-data?
multipart/form-data的基础是post请求,即基于post请求来实现的
multipart/form-data形式的post与普通post请求的不同之处体现在请求头,请求体2个部分
1)请求头:
必须包含Content-Type信息,且其值也必须规定为multipart/form-data,同时还需要规定一个内容分割符用于分割请求体中不同参数的内容(普通post请求的参数分割符默认为&,参数与参数值的分隔符为=)。
具体的头信息格式如下:
Content-Type: multipart/form-data; boundary=${bound}
其中${bound} 是一个占位符,代表我们规定的具体分割符;可以自己任意规定,但为了避免和正常文本重复了,尽量要使用复杂一点的内容。如:—0016e68ee29c5d515f04cedf6733
比如有一个body为:
--0016e68ee29c5d515f04cedf6733\r\nContent-Type: text/plain; charset=ISO-8859-1\r\nContent-Disposition: form-data; name=text\r\nContent-Transfer-Encoding: quoted-printable\r\n\r\nwords words words wor=\r\nds words words =\r\nwords words wor=\r\nds words words =\r\nwords words\r\n--0016e68ee29c5d515f04cedf6733\r\nContent-Type: text/plain; charset=ISO-8859-1\r\nContent-Disposition: form-data; name=submit\r\n\r\nSubmit\r\n--0016e68ee29c5d515f04cedf6733--

2)请求体:
它也是一个字符串,不过和普通post请求体不同的是它的构造方式。普通post请求体是简单的键值对连接,格式如下:
k1=v1&k2=v2&k3=v3
而multipart/form-data则是添加了分隔符、参数描述信息等内容的构造体。
具体格式如下:
--${bound}
Content-Disposition: form-data; name="Filename" //第一个参数,相当于k1;然后回车;然后是参数的值,即v1
HTTP.pdf //参数值v1
--${bound} //其实${bound}就相当于上面普通post请求体中的&的作用
Content-Disposition: form-data; name="file000"; filename="HTTP协议详解.pdf" //这里说明传入的是文件,下面是文件提
Content-Type: application/octet-stream //传入文件类型,如果传入的是.jpg,则这里会是image/jpeg %PDF-1.5
file content
%%EOF
--${bound}
Content-Disposition: form-data; name="Upload"
Submit Query
--${bound}--
都是以${bound}为开头的,并且最后一个${bound}后面要加—

test.go

package main

import (
	"bytes"
	"fmt"
	"io"
	"io/ioutil"
	"mime/multipart"
	"net/http"
	"os"
	"path/filepath"
)

func main() {
	// 需要上传的文件路径
	filePath := "image_2023_06_29T11_46_39_023Z.png"

	// 打开要上传的文件
	file, err := os.Open(filePath)
	if err != nil {
		fmt.Println("Failed to open file:", err)
		return
	}
	defer file.Close()

	// 创建multipart.Writer,用于构造multipart/form-data格式的请求体
	var requestBody bytes.Buffer
	multipartWriter := multipart.NewWriter(&requestBody)

	// 创建一个multipart.Part,用于表示文件字段
	part, err := multipartWriter.CreateFormFile("uploadfile", filepath.Base(filePath))
	if err != nil {
		fmt.Println("Failed to create form file:", err)
		return
	}

	// 将文件内容复制到multipart.Part中
	_, err = io.Copy(part, file)
	if err != nil {
		fmt.Println("Failed to copy file content:", err)
		return
	}

	// 添加其他表单字段
	multipartWriter.WriteField("title", "My file")

	// 关闭multipart.Writer,以便写入Content-Type和boundary
	err = multipartWriter.Close()
	if err != nil {
		fmt.Println("Failed to close multipart writer:", err)
		return
	}

	// 创建HTTP请求
	req, err := http.NewRequest("POST", "http://127.0.0.1:8181/upload", &requestBody)
	if err != nil {
		fmt.Println("Failed to create request:", err)
		return
	}

	// 设置Content-Type为multipart/form-data
	req.Header.Set("Content-Type", multipartWriter.FormDataContentType())

	// 发送HTTP请求
	client := http.DefaultClient
	resp, err := client.Do(req)
	if err != nil {
		fmt.Println("Failed to send request:", err)
		return
	}
	defer resp.Body.Close()

	// 处理响应
	respBody, err := ioutil.ReadAll(resp.Body)
	if err != nil {
		fmt.Println("Failed to read response:", err)
		return
	}
	fmt.Println("Response:", string(respBody))
}

编译执行:

go build test.go 

./test 

运行结果展示:

Go语言使用net/http实现简单登录验证和文件上传功能

Go语言使用net/http实现简单登录验证和文件上传功能文章来源地址https://www.toymoban.com/news/detail-510020.html

到了这里,关于Go语言使用net/http实现简单登录验证和文件上传功能的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处: 如若内容造成侵权/违法违规/事实不符,请点击违法举报进行投诉反馈,一经查实,立即删除!

领支付宝红包 赞助服务器费用

相关文章

  • Go语言 -- Web开发基础学习 net/http包

    Go 是一个开源的编程语言,它能让构造简单、可靠且高效的软件变得容易。 Go语言最擅长的领域就是Web开发,此贴是本人入门完go语法基础后学习Web开发的学习笔记。 新建go文件hello_world.go 写入: 在命令行运行: go run ./hello_world.go 可以发现控制台输出以下信息 通过上述代码

    2024年02月06日
    浏览(52)
  • 【设计模式】使用 go 语言实现简单工厂模式

    最近在看《大话设计模式》,这本书通过对话形式讲解设计模式的使用场景,有兴趣的可以去看一下。 第一篇讲的是 简单工厂模式 ,要求输入两个数和运算符号,得到运行结果。 这个需求不难,难就难在类要怎么设计,才能达到可复用、维护性强、可拓展和灵活性高。 运

    2024年02月05日
    浏览(48)
  • asp.net mvc实现系统登录及验证功能

    在网上购物或者实际的使用过程中经常遇到这样的一个场景:你必须输入用户米/密码,进行登录。登录完成后,界面自动跳转到之前的界面或者主页。具体下面的三个图所示。 在ASP.NET MVC中有个功能是身份认证(就是使用用户名和密码登录的问题),以及使用角色登录的功能

    2024年02月02日
    浏览(37)
  • SpringBoot实现简单的登录验证码

    参考了一些资料,完成了这个验证码的功能,下面记录一下功能的实现过程。 后台生成验证码图片,将图片传到前台。 后台在session中保存验证码内容。 前台输入验证码后传到后台在后台取出session中保存的验证码进行校验。 1、建一个config 我是建了一个名叫KaptchaConfig的con

    2024年02月10日
    浏览(29)
  • Curl- go的自带包 net/http实现

    case http 包中的 Request 发送请求的步骤:1. 创建客户端 2. 发送请求 3. 接受响应 http.NewRequest method get,post,delete,put url body :可以是多种形式的数据包含在请求体中 我们可以看出这个 : body 是一个 io.Reader 所以 Request 的请求体就是字节流。所以制定编码方式-》用 header 指定

    2024年01月20日
    浏览(41)
  • JavaGui实现登录界面编写+实现账号密码验证登录+文件存储

    目录 标题一: 登录界面编写 标题二;登录界面之注册(一个类)编写  标题三:登录界面之登录编写  在登录界面这里,我们先编写一个登录界面出来,这只是一个界面,还没有实现验证账号密码和注册的功能,但得有这个界面做媒介 。 界面如下:   1.登陆界面代码在这里

    2024年02月08日
    浏览(57)
  • go语言简单实现区块链

            在本文中,我们将使用Go语言来实现一个简单的区块链系统,包括区块生成、交易处理和区块打印、保存区块链等功能。 在开始之前,先确保计算机上安装了以下内容: Go编程语言:您可以从Go官方网站下载并安装Go。 Go开发环境:设置Go开发环境,包括文本编辑器

    2024年04月16日
    浏览(38)
  • Apinto 网关: Go语言实现 HTTP 转 gRPC

    gRPC  是由 Google 开发的一个高性能、通用的开源RPC框架,主要面向移动应用开发且基于  HTTP/2  协议标准而设计,同时支持大多数流行的编程语言。 gRPC  基于  HTTP/2  协议传输,  HTTP/2  相比  HTTP1.x 有以下优势: 采用二进制格式传输协议,支持多路复用。 支持通过同一个连

    2024年02月07日
    浏览(38)
  • 使用Go语言编写HTTP代理服务器

    在Go语言中,编写一个HTTP代理服务器相对简单且直观。代理服务器的主要职责是接收客户端的请求,然后将请求转发到目标服务器,再将目标服务器的响应返回给客户端。下面是一个简单的示例,展示如何使用Go语言编写一个基本的HTTP代理服务器: go 复制代码 package  main i

    2024年01月18日
    浏览(55)
  • 【go语言开发】redis简单使用

    本文主要介绍redis安装和使用。首先安装redis依赖库,这里是v8版本;然后连接redis,完成基本配置;最后测试封装的工具类 欢迎大家访问个人博客网址:https://www.maogeshuo.com,博主努力更新中… 参考文件: Yaml文件配置,Config使用 Log日志封装 常用工具类封装 命令行安装redis

    2024年03月12日
    浏览(59)

觉得文章有用就打赏一下文章作者

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

请作者喝杯咖啡吧~博客赞助

支付宝扫一扫领取红包,优惠每天领

二维码1

领取红包

二维码2

领红包