2018年02月08日 10:07:13 冷月醉雪 阅读数:346 标签: golangHTTP文件上传更多

个人分类: Go
 
版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lengyuezuixue/article/details/79277691

首先,我们在服务器端设定两个路由,/upload用于文件上传,/files/*用于文件下载。

  1.  
    const maxUploadSize = 2 * 1024 * 2014 // 2 MB
  2.  
    const uploadPath = "./tmp"
  3.  
     
  4.  
    func main() {
  5.  
    http.HandleFunc("/upload", uploadFileHandler())
  6.  
     
  7.  
    fs := http.FileServer(http.Dir(uploadPath))
  8.  
    http.Handle("/files/", http.StripPrefix("/files", fs))
  9.  
     
  10.  
    log.Print("Server started on localhost:8080, use /upload for uploading files and /files/{fileName} for downloading files.")
  11.  
    log.Fatal(http.ListenAndServe(":8080", nil))
  12.  
    }

我们还将要上传的目标目录,以及我们接受的最大文件大小定义为常量。注意这里,整个文件服务的概念是如此的简单--我们仅使用标准库中的工具,使用http.FileServer创建一个HTTP处理程序,它将使用http.Dir(uploadPath)提供的目录来上传文件。

现在我们只需要实现uploadFileHander.这个处理程序将包含以下功能:

·验证文件最大值;

·从请求验证文件和POST参数

·检查所提供的文件类型

·创建一个随机文件名

·将文件写入硬盘

·处理所有错误,如果一切顺利返回成功消息

第一步,我们定义处理程序:

  1.  
    func uploadFileHandler() http.HandlerFunc {
  2.  
    return http.HandlerFunc(func(w http.ResponseWriter, r *http.Request) {

然后,我们使用http.MaxBytesReader验证文件大小,当文件大小大于设定值时它将返回一个错误。错误将被一个助手程序renderError进行处理,它返回错误信息以及对应的HTTP状态码。

  1.  
    r.Body = http.MaxBytesReader(w, r.Body, maxUploadSize)
  2.  
    if err := r.ParseMultipartForm(maxUploadSize); err != nil {
  3.  
    renderError(w, "FILE_TOO_BIG", http.StatusBadRequest)
  4.  
    return
  5.  
    }

如果文件大小验证通过,我们将检查并解析表单参数类型和上传的文件,并读取文件。在本例中,wield清晰起见,我们不使用花哨的io.Reader和io.Writer接口,我们只是简单的将文件读取到一个字节数组中,这点我们后面会写到。

  1.  
    fileType := r.PostFormValue("type")
  2.  
    file, _, err := r.FormFile("uploadFile")
  3.  
    if err != nil {
  4.  
    renderError(w, "INVALID_FILE", http.StatusBadRequest)
  5.  
    return
  6.  
    }
  7.  
    defer file.Close()
  8.  
    fileBytes, err := ioutil.ReadAll(file)
  9.  
    if err != nil {
  10.  
    renderError(w, "INVALID_FILE", http.StatusBadRequest)
  11.  
    return
  12.  
    }

现在我们成功的验证了文件的大小,并读取了文件,接下来我们该检验文件的类型了。一种廉价但是并不安全的方式,只检查文件扩展名,并相信用户没有改变它,但是对于一个正式的项目来说并不应该这么做。

幸运的是,Go标准库提供给我们一个Http.DetectConntectType函数,这个函数基于mimesniff算法,祝需要读取文件的512个字节就能够判断文件的类型。

  1.  
    iletype := http.DetectContentType(fileBytes)
  2.  
    if filetype != "image/jpeg" && filetype != "image/jpg" &&
  3.  
    filetype != "image/gif" && filetype != "image/png" &&
  4.  
    filetype != "application/pdf" {
  5.  
    renderError(w, "INVALID_FILE_TYPE", http.StatusBadRequest)
  6.  
    return
  7.  
    }

在实际应用程序中,我们可能会使用文件元数据做一些事情,例如将其保存到数据库或将其推送到外部服务--以任何方式,我们将解析和操作元数据。这里我们创建一个随机的新名字并将新文件名记录下来。

  1.  
    fileName := randToken(12)
  2.  
    fileEndings, err := mime.ExtensionsByType(fileType)
  3.  
    if err != nil {
  4.  
    renderError(w, "CANT_READ_FILE_TYPE", http.StatusInternalServerError)
  5.  
    return
  6.  
    }
  7.  
    newPath := filepath.Join(uploadPath, fileName+fileEndings[0])
  8.  
    fmt.Printf("FileType: %s, File: %s\n", fileType, newPath)

马上就大功告成了,只剩下一个关键步骤-写文件。如上文提供的,我们只需要复制读取的二进制文件到新创建的名为newFile的文件处理程序中。

如果所有部分都没问题,我们给用户返回一个i额SUCCESS信息。

  1.  
    newFile, err := os.Create(newPath)
  2.  
    if err != nil {
  3.  
    renderError(w, "CANT_WRITE_FILE", http.StatusInternalServerError)
  4.  
    return
  5.  
    }
  6.  
    defer newFile.Close()
  7.  
    if _, err := newFile.Write(fileBytes); err != nil {
  8.  
    renderError(w, "CANT_WRITE_FILE", http.StatusInternalServerError)
  9.  
    return
  10.  
    }
  11.  
    w.Write([]byte("SUCCESS"))

这样就可以了。你可对这个简单的例子进行测试,使用虚拟的文件上传HTML页面,cURL或工具例如postman。

Golang HTTP文件上传的更多相关文章

  1. golang实现文件上传权限验证(超简单)

    Go语言创建web server非常简单,部署也很容易,不像IIS.Apache等那么重量级,需要各种依赖.配置.一些功能单一的web 服务,用Go语言开发特别适合.http文件上传下载服务,在很多地 ...

  2. golang学习之文件上传

    首先是上传页面upload.html: <!doctype html> <html> <head> <meta charset="utf-8&quo ...

  3. golang实现图片上传

    golang实现图片上传 该代码为使用beego实现前后端图片上传.话不多说,直接上代码. 1.前端代码 html代码: <div class="col-5 f-l text text ...

  4. Rocket框架多文件上传,介绍rocket_upload 使用

    不知道你的体会是什么,我从C切换到Rust以来,最大的感受并不是语法方面的---那些方面已经有足够多人抱怨而又享受着了.我最大的感受是终于把Web编程工具,同系统编程工具统一了起来. C/C++其实也 ...

  5. jquery.uploadify文件上传组件

    1.jquery.uploadify简介 在ASP.NET中上传的控件有很多,比如.NET自带的FileUpload,以及SWFUpload,Uploadify等等,尤其后面两个控件的用户体验比较好, ...

  6. 11、Struts2 的文件上传和下载

    文件上传 表单准备 要想使用 HTML 表单上传一个或多个文件 须把 HTML 表单的 enctype 属性设置为 multipart/form-data 须把 HTML 表单的method 属性设置 ...

  7. Java FtpClient 实现文件上传服务

    一.Ubuntu 安装 Vsftpd 服务 1.安装 sudo apt-get install vsftpd 2.添加用户(uftp) sudo useradd -d /home/uftp -s /b ...

  8. 小兔Java教程 - 三分钟学会Java文件上传

    今天群里正好有人问起了Java文件上传的事情,本来这是Java里面的知识点,而我目前最主要的精力还是放在了JS的部分.不过反正也不麻烦,我就专门开一贴来聊聊Java文件上传的基本实现方法吧. 话不多说 ...

  9. ,net core mvc 文件上传

    工作用到文件上传的功能,在这个分享下 ~~ Controller: public class PictureController : Controller { private IHostingEnvi ...

随机推荐

  1. nGrinder工具进行接口性能测试

    1.背景 之前在这篇文章中性能测试初探—接口性能测试介绍过nGrinder,本文将介绍在nGrinder脚本中使用资源文件中数据作为接口参数和解析生成的CSV结果,生成TPS标准差,TPS波动率,最小 ...

  2. weblogic 内存 及 内存溢出

    . 区分JVM虚拟机选项:Xms Xmx PermSize MaxPermSize JVM限制:相关操作系统的数据模型(32-bt还是64-bit)限制:系统的可用虚拟内存限制:系统的可用物理内存限制 ...

  3. 算法笔记_154:算法提高 日期计算(Java)

    目录 1 问题描述 2 解决方案   1 问题描述 问题描述 已知2011年11月11日是星期五,问YYYY年MM月DD日是星期几?注意考虑闰年的情况.尤其是逢百年不闰,逢400年闰的情况. 输入格式 ...

  4. 从头学习MVC4基础之视图

    实例一:首先简单显示实例: 控制器代码: public class WujyTestController : Controller { public ActionResult Index() { Li ...

  5. webpack 编译html模板文件

    1.项目结构 安装loader: npm i html-loader --save-dev npm i ejs-loader --save-dev 2.模板文件layer.html <div c ...

  6. SEO优化实践操作

    合理的title.description.keywords:搜索对着三项的权重逐个减小,title值强调重点即可,重要关键词出现不要超过2次,而且要靠前,不同页面title要有所不同:descript ...

  7. SQL Server 性能调优(方法论)【转】

    目录 确定思路 wait event的基本troubleshooting 虚拟文件信息(virtual file Statistics) 性能指标 执行计划缓冲的使用 总结 性能调优很难有一个固定的理 ...

  8. 解决Android SDK Manager下载问题和android studio每次启动都要在fetching Android sdk compoment information

    1.能解决国内访问Google服务器的困难启动 Android SDK Manager ,打开主界面,依次选择「Tools」.「Options...」,弹出『Android SDK Manager - ...

  9. 【NEWS】 ADempiere发布ADempiere 3.8.0路线图【2013年7月28日】

    发布源:http://osssme.org/cms/?q=node/17 本以为ADempiere”已死“,但是看到ADempiere的WIKI上大概在从5月28日开始添加WIKI以来,经过多次更新后 ...

  10. 复制web项目,启动的时候的工程名如何改变

    右键项目->properties 然后 搜索 web  出现 Web Project Settings 右边看见  Context root 改成你希望的名字. 然后重启elipse