三分钟用Golang搭建一个HTTP文件上传下载服务器

这篇具有很好参考价值的文章主要介绍了三分钟用Golang搭建一个HTTP文件上传下载服务器。希望对大家有所帮助。如果存在错误或未考虑完全的地方,请大家不吝赐教,您也可以点击"举报违法"按钮提交疑问。

背景

简单需要一个文件服务器来传递数据,只要两个功能,一个上传接口,一个下载接口。

选用go http模块实现,比nginx、ftp等更方便快捷。

需求整理

  • 上传接口"/v1/file_upload/"
  • 上传接口增加简单BasicAuth鉴权
  • 上传成功返回下载URL
    json格式返回

电梯直达

只想文件上传服务器测试接口,以下电梯直达即可
CSDN 5积分下载
白嫖

测试效果

三分钟用Golang搭建一个HTTP文件上传下载服务器三分钟用Golang搭建一个HTTP文件上传下载服务器

GO代码实现

package main

import (
	"bytes"
	"encoding/base64"
	"encoding/json"
	"flag"
	"fmt"
	"io"
	"log"
	"net/http"
	"os"
	"path/filepath"
	"strings"
)

type ViewFunc func(http.ResponseWriter, *http.Request)

func http_resp(code int, msg string, w http.ResponseWriter) {
	var Result map[string]interface{}
	Result = make(map[string]interface{})

	Result["code"] = code
	Result["msg"] = msg

	data, err := json.Marshal(Result)
	if err != nil {
		log.Printf("%v\n", err)
	}

	w.Write([]byte(string(data)))
}

func upload(w http.ResponseWriter, r *http.Request) {
	if r.Method == "GET" {
		t, _ := template.ParseFiles("upload.html")
		t.Execute(w, nil)
		return
	}
	
	contentType := r.Header.Get("content-type")
	contentLen := r.ContentLength

	if !strings.Contains(contentType, "multipart/form-data") {
		http_resp(-1001, "The content-type must be multipart/form-data", w)
		return
	}
	//限制最大文件大小
	if contentLen >= 50*1024*1024 {
		http_resp(-1002, "Failed to large,limit 50MB", w)
		return
	}

	err := r.ParseMultipartForm(50 * 1024 * 1024)
	if err != nil {
		http_resp(-1003, "Failed to ParseMultipartForm", w)
		return
	}

	if len(r.MultipartForm.File) == 0 {
		http_resp(-1004, "File is NULL", w)
		return
	}

	var Result map[string]interface{}
	Result = make(map[string]interface{})

	Result["code"] = 0
	DownLoadUrl := "http://192.168.10.9:8080/"

	FileCount := 0
	for _, headers := range r.MultipartForm.File {
		for _, header := range headers {
			log.Printf("recv file: %s\n", header.Filename)

			filePath := filepath.Join("./upload", header.Filename)
			dstFile, err := os.OpenFile(filePath, os.O_WRONLY|os.O_CREATE, 0666)
			if err != nil {
				log.Printf("Create file %s error: %s\n", filePath, err)
				return
			}
			srcFile, err := header.Open()
			if err != nil {
				log.Printf("Open header failed: %s\n", err)
			}
			_, err = io.Copy(dstFile, srcFile)
			if err != nil {
				log.Printf("Write file %s error: %s\n", filePath, err)
			}
			_, _ = srcFile.Close(), dstFile.Close()
			FileCount++
			name := fmt.Sprintf("file%d_url", FileCount)
			Result[name] = (DownLoadUrl + header.Filename)
		}
	}
	data, err := json.Marshal(Result)
	if err != nil {
		log.Printf("%v \n", err)
	}
	w.Write([]byte(string(data)))
}

func BasicAuth(f ViewFunc, user, passwd []byte) ViewFunc {
	return func(w http.ResponseWriter, r *http.Request) {
		basicAuthPrefix := "Basic "

		// 获取 request header
		auth := r.Header.Get("Authorization")
		// 如果是 http basic auth
		if strings.HasPrefix(auth, basicAuthPrefix) {
			// 解码认证信息
			payload, err := base64.StdEncoding.DecodeString(
				auth[len(basicAuthPrefix):],
			)
			if err == nil {
				pair := bytes.SplitN(payload, []byte(":"), 2)
				if len(pair) == 2 && bytes.Equal(pair[0], user) &&
					bytes.Equal(pair[1], passwd) {
					// 执行被装饰的函数
					f(w, r)
					return
				}
			}
		}

		// 认证失败,提示 401 Unauthorized
		// Restricted 可以改成其他的值
		w.Header().Set("WWW-Authenticate", `Basic realm="Restricted"`)
		// 401 状态码
		w.WriteHeader(http.StatusUnauthorized)
	}
}

func main() {
	addr := flag.String("addr", "0.0.0.0:8080", "服务绑定地址端口")
	user := flag.String("user", "", "http认证用户名(如果用户名为空,则不需要认证)")
	psw := flag.String("psw", "", "http认证密码")
	root := flag.String("root", "./upload/", "文件服务根目录")
	flag.Parse()

	os.Mkdir(*root, 0777)

	http_user := []byte(*user)
	http_psw := []byte(*psw)

	log.Printf("http server listen on %v \n", *addr)

	if *user != "" {
		http.HandleFunc("/v1/file_upload", BasicAuth(upload, http_user, http_psw))
	} else {
		http.HandleFunc("/v1/file_upload", upload)
	}

	http.Handle("/", http.StripPrefix("/", http.FileServer(http.Dir(*root))))
	err := http.ListenAndServe(*addr, nil)
	if err != nil {
		log.Printf("%v", err)
	}
}

网页上传

新建文件upload.html放到http服务器root目录。例如upload文件夹

<!DOCTYPE html>
 <html>
      <head>
      <meta charset="utf-8">
      <title>go 上传test</title>
     </head>
<body>
<form method="POST" action="/v1/file_upload" enctype="multipart/form-data" >
<input type="file" name="uploadfile" />
<input type="submit" value="上传">
</form>
</body>
</html>

三分钟用Golang搭建一个HTTP文件上传下载服务器
三分钟用Golang搭建一个HTTP文件上传下载服务器

参考

《如何为 HTTP Server 增加 HTTP Basic Auth 》文章来源地址https://www.toymoban.com/news/detail-512494.html

到了这里,关于三分钟用Golang搭建一个HTTP文件上传下载服务器的文章就介绍完了。如果您还想了解更多内容,请在右上角搜索TOY模板网以前的文章或继续浏览下面的相关文章,希望大家以后多多支持TOY模板网!

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

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

相关文章

  • 调用hutool包调用http接口处理文件流-文件的上传下载工具类

    hutool工具类get请求获取流: InputStream inputStream = HttpRequest.get(fileUrl).execute().bodyStream(); hutool工具类post请求上传文件流: String resp = HttpRequest.post(url).header(Header.CONTENT_TYPE.getValue(), ContentType.MULTIPART.getValue()).form(params).execute().body(); 完成代码

    2024年01月17日
    浏览(56)
  • Golang Gin框架HTTP上传文件

    HTTP上传的文件的原理 HTTP协议的文件上传是通过HTTP POST请求实现的,使用multipart/form-data格式将待上传的文件放入请求体中。 服务器根据请求头中的boundary参数来解析请求体,并根据Content-Disposition字段获取文件名等信息,根据Content-Type字段判断文件类型并保存到相应位置。

    2024年02月05日
    浏览(38)
  • Java实现HTTP的上传与下载

    相信很多人对于java文件下载的过程都存在一些疑惑,比如下载上传文件会不会占用vm内存,上传/下载大文件会不会导致oom。下面从字节流的角度看下载/上传的实现,可以更加深入理解文件的上传和下载功能。 首先明确,文件下载不仅仅只有下载方,还有服务端也就是返回文

    2024年02月10日
    浏览(36)
  • SpringBoot+vue文件上传&下载&预览&大文件分片上传&文件上传进度

    SpringBoot+vue 大文件分片下载 Blob File spark-md5根据文件内容生成hash 大文件分片上传(批量并发,手动上传)vue组件封装-form组件 vue上传大文件/视频前后端(java)代码 springboot+vue自定义上传图片及视频 SpringBoot + VUE实现前台上传文件获取实时进度( 使用commons-fileupload设置上传监听

    2024年02月05日
    浏览(74)
  • 文件上传及oss简单上传及下载

    文件上传就是通过io流复制到浏览器的过程 快速实现文件上传功能 1.后台实现文件上传功能  定义controllere 定义serevice 文件上传不会直接上传真是的目录,它一定要经过一个临时目录的中转以后,才会上传到真是目录。作用: 防止上传出现网络断开,或者用户上传直接刷新或

    2023年04月09日
    浏览(38)
  • 【Postman】 测试文件上传、下载 一、使用PostMan测试文件上传接口

    1、、选择post请求方式,输入请求地址   二、填写Headers  一般是自动生成的 Key:Content-Type Value:multipart/form-data 如下图   三、填写body 选择form-data     然后选择文件file    点击添加文件,最后发送即可   1、反馈异常,先排查 Headers中 Conten-Type 与 ”文件类型“是否匹配  

    2024年02月11日
    浏览(62)
  • 前端常用的上传下载文件的几种方式,直接上传、下载文件,读取.xlsx文件数据,导出.xlsx数据

    1.1根据文件流Blob进行下载 1.2根据下载文件链接直接进行下载 html

    2024年02月12日
    浏览(44)
  • 下载文件 + 上传文件

    记录一下js实现下载文件的方式 下载文件 方式一:a 链接下载:模拟a链接的点击,把后端返回的下载地址设置给a链接的href属性 2. 文件流下载 前端接收 type: “application/octet-stream“ 格式的数据并下载,还有后端既返回octet-stream还返回JSON数据时的处理方法, 后端改了一下文件下

    2024年02月12日
    浏览(51)
  • 文件上传下载系列——如何实现文件秒传

    🎃简介: 👻核心思想: MD5是什么? 实现步骤: 🎄实操: 1、java生成文件MD5码 2、javascript生成文件MD5码 ⛳️基于秒传的分片上传下载 上传: 下载: 🍢MD5存储位置 1、持久化到数据库中 2、存储到redis中 🎋总结         文件秒传是指在文件上传过程中,如果上传的文件

    2024年02月01日
    浏览(39)
  • Selenium基础 — 文件上传&文件下载

    说明: 文件上传是web页面上很常见的一个功能,用脚本去实现文件上传很简单。 一般场景:在页面中的上传按钮是一个input标签,其中type属性为 type=\\\"file\\\" ,这种可以用selenium提供的 send_keys() 方法轻松解决。 示例: 页面代码片段: 脚本代码:  提示: 另外一种非input标签的

    2024年02月02日
    浏览(37)

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

支付宝扫一扫打赏

博客赞助

微信扫一扫打赏

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

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

二维码1

领取红包

二维码2

领红包