Golang HTTP文件上传
首先,我们在服务器端设定两个路由,/upload用于文件上传,/files/*用于文件下载。
- const maxUploadSize = 2 * 1024 * 2014 // 2 MB
- const uploadPath = "./tmp"
- func main() {
- http.HandleFunc("/upload", uploadFileHandler())
- fs := http.FileServer(http.Dir(uploadPath))
- http.Handle("/files/", http.StripPrefix("/files", fs))
- log.Print("Server started on localhost:8080, use /upload for uploading files and /files/{fileName} for downloading files.")
- log.Fatal(http.ListenAndServe(":8080", nil))
- }
我们还将要上传的目标目录,以及我们接受的最大文件大小定义为常量。注意这里,整个文件服务的概念是如此的简单--我们仅使用标准库中的工具,使用http.FileServer创建一个HTTP处理程序,它将使用http.Dir(uploadPath)提供的目录来上传文件。
现在我们只需要实现uploadFileHander.这个处理程序将包含以下功能:
·验证文件最大值;
·从请求验证文件和POST参数
·检查所提供的文件类型
·创建一个随机文件名
·将文件写入硬盘
·处理所有错误,如果一切顺利返回成功消息
第一步,我们定义处理程序:
- func uploadFileHandler() http.HandlerFunc {
- return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {
然后,我们使用http.MaxBytesReader验证文件大小,当文件大小大于设定值时它将返回一个错误。错误将被一个助手程序renderError进行处理,它返回错误信息以及对应的HTTP状态码。
- r.Body = http.MaxBytesReader(w, r.Body, maxUploadSize)
- if err := r.ParseMultipartForm(maxUploadSize); err != nil {
- renderError(w, "FILE_TOO_BIG", http.StatusBadRequest)
- return
- }
如果文件大小验证通过,我们将检查并解析表单参数类型和上传的文件,并读取文件。在本例中,wield清晰起见,我们不使用花哨的io.Reader和io.Writer接口,我们只是简单的将文件读取到一个字节数组中,这点我们后面会写到。
- fileType := r.PostFormValue("type")
- file, _, err := r.FormFile("uploadFile")
- if err != nil {
- renderError(w, "INVALID_FILE", http.StatusBadRequest)
- return
- }
- defer file.Close()
- fileBytes, err := ioutil.ReadAll(file)
- if err != nil {
- renderError(w, "INVALID_FILE", http.StatusBadRequest)
- return
- }
现在我们成功的验证了文件的大小,并读取了文件,接下来我们该检验文件的类型了。一种廉价但是并不安全的方式,只检查文件扩展名,并相信用户没有改变它,但是对于一个正式的项目来说并不应该这么做。
幸运的是,Go标准库提供给我们一个Http.DetectConntectType函数,这个函数基于mimesniff算法,祝需要读取文件的512个字节就能够判断文件的类型。
- iletype := http.DetectContentType(fileBytes)
- if filetype != "image/jpeg" && filetype != "image/jpg" &&
- filetype != "image/gif" && filetype != "image/png" &&
- filetype != "application/pdf" {
- renderError(w, "INVALID_FILE_TYPE", http.StatusBadRequest)
- return
- }
在实际应用程序中,我们可能会使用文件元数据做一些事情,例如将其保存到数据库或将其推送到外部服务--以任何方式,我们将解析和操作元数据。这里我们创建一个随机的新名字并将新文件名记录下来。
- fileName := randToken(12)
- fileEndings, err := mime.ExtensionsByType(fileType)
- if err != nil {
- renderError(w, "CANT_READ_FILE_TYPE", http.StatusInternalServerError)
- return
- }
- newPath := filepath.Join(uploadPath, fileName+fileEndings[0])
- fmt.Printf("FileType: %s, File: %s\n", fileType, newPath)
马上就大功告成了,只剩下一个关键步骤-写文件。如上文提供的,我们只需要复制读取的二进制文件到新创建的名为newFile的文件处理程序中。
如果所有部分都没问题,我们给用户返回一个i额SUCCESS信息。
- newFile, err := os.Create(newPath)
- if err != nil {
- renderError(w, "CANT_WRITE_FILE", http.StatusInternalServerError)
- return
- }
- defer newFile.Close()
- if _, err := newFile.Write(fileBytes); err != nil {
- renderError(w, "CANT_WRITE_FILE", http.StatusInternalServerError)
- return
- }
- w.Write([]byte("SUCCESS"))
这样就可以了。你可对这个简单的例子进行测试,使用虚拟的文件上传HTML页面,cURL或工具例如postman。
Golang HTTP文件上传的更多相关文章
- golang实现文件上传权限验证(超简单)
Go语言创建web server非常简单,部署也很容易,不像IIS.Apache等那么重量级,需要各种依赖.配置.一些功能单一的web 服务,用Go语言开发特别适合.http文件上传下载服务,在很多地 ...
- golang学习之文件上传
首先是上传页面upload.html: <!doctype html> <html> <head> <meta charset="utf-8&quo ...
- golang实现图片上传
golang实现图片上传 该代码为使用beego实现前后端图片上传.话不多说,直接上代码. 1.前端代码 html代码: <div class="col-5 f-l text text ...
- Rocket框架多文件上传,介绍rocket_upload 使用
不知道你的体会是什么,我从C切换到Rust以来,最大的感受并不是语法方面的---那些方面已经有足够多人抱怨而又享受着了.我最大的感受是终于把Web编程工具,同系统编程工具统一了起来. C/C++其实也 ...
- jquery.uploadify文件上传组件
1.jquery.uploadify简介 在ASP.NET中上传的控件有很多,比如.NET自带的FileUpload,以及SWFUpload,Uploadify等等,尤其后面两个控件的用户体验比较好, ...
- 11、Struts2 的文件上传和下载
文件上传 表单准备 要想使用 HTML 表单上传一个或多个文件 须把 HTML 表单的 enctype 属性设置为 multipart/form-data 须把 HTML 表单的method 属性设置 ...
- Java FtpClient 实现文件上传服务
一.Ubuntu 安装 Vsftpd 服务 1.安装 sudo apt-get install vsftpd 2.添加用户(uftp) sudo useradd -d /home/uftp -s /b ...
- 小兔Java教程 - 三分钟学会Java文件上传
今天群里正好有人问起了Java文件上传的事情,本来这是Java里面的知识点,而我目前最主要的精力还是放在了JS的部分.不过反正也不麻烦,我就专门开一贴来聊聊Java文件上传的基本实现方法吧. 话不多说 ...
- ,net core mvc 文件上传
工作用到文件上传的功能,在这个分享下 ~~ Controller: public class PictureController : Controller { private IHostingEnvi ...
随机推荐
- Linux crond实例
linux系统的定时任务: 1:linux系统自身定期执行的任务工作:系统周期性执行的任务工作,如轮询系统日志,备份系统数据,清理系统缓存等. [root@10-4-5-9 ~]# ll /var/l ...
- Android开发之短信
短信主要界面:会话列表,会话详情,新建短信. 联系人主要界面:联系人列表,编辑联系人. 创建首页.首页由TabActivity表现. 在Android4.1中,TabActivity处于保护状态. T ...
- 设置linux中tcp默认的20秒connect超时时间(转)
无论你用任何语言或者是网络库,你都可以设置网络操作的超时时间,特别是connect.read.write的超时时间. 你可以在代码中把超时时间设置任意大小值,但是connect方法会有一点特殊. co ...
- 为什么要设置Java环境变量(详解)[转]
从大二开始接触Java,之后是断断续续的学习.大三真正开始Java之旅,估计大部分初学者在学Java时被Java的环境变量搞的晕头转向,虽然找到了正确设置环境变量的方式,但其中的原因一知半解,设置压根 ...
- 如何使用T-SQL备份还原数据库及c#如何调用执行? C#中索引器的作用和实现。 jquery控制元素的隐藏和显示的几种方法。 localStorage、sessionStorage用法总结 在AspNetCore中扩展Log系列 - 介绍开源类库的使用(一) span<T>之高性能字符串操作实测
如何使用T-SQL备份还原数据库及c#如何调用执行? 准备材料:Microsoft SQL Server一部.需要还原的bak文件一只 一.备份 数据库备份语句:user master backup ...
- 引用、数组引用与指针引用、内联函数inline、四种类型转换运算符
一.引用 (1).引用是给一个变量起别名 定义引用的一般格式:类型 &引用名 = 变量名: 例如:int a=1; int &b=a;// b是a的别名,因此a和b是同一个单元 ...
- SIP/2.0 403 Forbidden(Invalid domain in From: header)
一.错误场景 FreeSWITCH通过网关和一台支持SIP的网关设备互联,一个呼叫发过去,收到这个错误. FreeSWITCH的地址是192.168.1.99. 网关设备的地址是192.168.1.2 ...
- SQL Server2005 两台服务器上的数据库互相同步(转载)
1.1测试环境 Item 发布机 A 订阅机 B OS Windows 2003 Server Windows 2003 Server SQL SQL Server 2005 企业版 SQL Serv ...
- mac shell终端编辑命令行快捷键——行首行尾
mac shell终端编辑命令行快捷键——行首行尾 ctrl+a //移到行首ctrl+e //移到行尾===========linux系统用============alt+a //移到光标所在单词首 ...
- Kernel ridge regression(KRR)
作者:桂. 时间:2017-05-23 15:52:51 链接:http://www.cnblogs.com/xingshansi/p/6895710.html 一.理论描述 Kernel ridg ...