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. python------@staticmethod和@classmethod的作用与区别

    一般来说,要使用某个类的方法,需要先实例化一个对象再调用方法. 而使用@staticmethod或@classmethod,就可以不需要实例化,直接类名.方法名()来调用. 这有利于组织代码,把某些应 ...

  2. UNIX网络编程卷2进程间通信读书笔记(二)—管道 (1)

    一.管道 管道的名称很形象,它就像是一个水管,我们从一端到水然后水从令一端流出.不同的是这里说的管道的两边都是进程.从一端往管道里写数据,其它进程可以从管道的另一端的把数据读出,从而实现了进程间通信的 ...

  3. 机器学习数学基础- gradient descent算法(上)

    为什么要了解点数学基础 学习大数据分布式计算时多少会涉及到机器学习的算法,所以理解一些机器学习基础,有助于理解大数据分布式计算系统(比如spark)的设计.机器学习中一个常见的就是gradient d ...

  4. 【Linux】cp命令

    用途 cp除了复制功能之外还可以建立快捷方式 全称 cp的全称为copy 参数 -a :相当于同时指定参数pdr -d :若文件为链接文件的属性(link file),则复制链接文件属性而非档案本身 ...

  5. iOS 全屏侧滑/UIScrollView/UISlider间滑动冲突

    代码地址如下:http://www.demodashi.com/demo/13848.html 效果预览 一.前期准备 有一个支持全屏侧滑返回的视图控制器ViewController,ViewCont ...

  6. MVC之Ajax.BeginForm使用详解之更新列表 mvc验证jquery.unobtrusive-ajax

    MVC之Ajax.BeginForm使用详解之更新列表   1.首先,请在配置文件设置如下:(该项默认都存在且为true) <add key="UnobtrusiveJavaScrip ...

  7. C#串口通信程序实现无感知签到与答题

    最近公司项目上线,之前利用串口通讯实现校牌的无感知签到程序, 项目上线以后刚刚好有时间把之前的出现的问题做下记录,废话不多,直接到主题 串口介绍: 串行接口简称串口,也称串行通信接口或串行通讯接口(通 ...

  8. git配置用户名邮箱

    通常会配置全局的 用户名 邮箱  例如 姓名@公司邮箱  姓名 git config --global user.name "姓名" git config --global use ...

  9. Android成长之路-手势库的创建

      手势库的创建: 使用SDK自带的例子GestureBuilder建立手势库,这个文件夹存在于android\android-sdk-windows \samples\android-10\Gest ...

  10. SeeSharpTools.JXI.DSP.Spectrum 使用

    _spectrumTask.Average.Mode = SeeSharpTools.JXI.DSP.Spectrum.SpectrumAverageMode.PeakHold; // NoAvera ...