加入收藏 | 设为首页 | 会员中心 | 我要投稿 李大同 (https://www.lidatong.com.cn/)- 科技、建站、经验、云计算、5G、大数据,站长网!
当前位置: 首页 > 大数据 > 正文

Golang HTTP文件上传

发布时间:2020-12-16 09:33:42 所属栏目:大数据 来源:网络整理
导读:2018年02月08日 10:07:13? 冷月醉雪 ? 阅读数:346? 标签:?golang HTTP 文件上传 更多 个人分类:?Go ? 版权声明:本文为博主原创文章,未经博主允许不得转载。 https://blog.csdn.net/lengyuezuixue/article/details/79277691 ? ?首先,我们在服务器端设定

2018年02月08日 10:07:13?冷月醉雪?阅读数:346?标签:?golang HTTP 文件上传

版权声明:本文为博主原创文章,未经博主允许不得转载。 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,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: %sn",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,http.StatusInternalServerError)
  9. ?
    return
  10. ?
    }
  11. ?
    w.Write([] byte("SUCCESS"))
? ?这样就可以了。你可对这个简单的例子进行测试,使用虚拟的文件上传HTML页面,cURL或工具例如postman。

(编辑:李大同)

【声明】本站内容均来自网络,其相关言论仅代表作者个人观点,不代表本站立场。若无意侵犯到您的权利,请及时与联系站长删除相关内容!

    推荐文章
      热点阅读