Golang HTTP文件上传
本文内容纲要:
-2018年02月08日10:07:13冷月醉雪阅读数:346标签:golangHTTP文件上传更多
2018年02月08日10:07:13冷月醉雪阅读数:346标签:golangHTTP文件上传更多
个人分类:Go
版权声明:本文为博主原创文章,未经博主允许不得转载。https://blog.csdn.net/lengyuezuixue/article/details/79277691
首先,我们在服务器端设定两个路由,/upload用于文件上传,/files/*用于文件下载。
- constmaxUploadSize=2*1024*2014//2MB
- constuploadPath="./tmp"
- funcmain(){
- http.HandleFunc("/upload",uploadFileHandler())
- fs:=http.FileServer(http.Dir(uploadPath))
- http.Handle("/files/",http.StripPrefix("/files",fs))
- log.Print("Serverstartedonlocalhost:8080,use/uploadforuploadingfilesand/files/{fileName}fordownloadingfiles.")
- log.Fatal(http.ListenAndServe(":8080",nil))
- }
我们还将要上传的目标目录,以及我们接受的最大文件大小定义为常量。注意这里,整个文件服务的概念是如此的简单--我们仅使用标准库中的工具,使用http.FileServer创建一个HTTP处理程序,它将使用http.Dir(uploadPath)提供的目录来上传文件。
现在我们只需要实现uploadFileHander.这个处理程序将包含以下功能:
·验证文件最大值;
·从请求验证文件和POST参数
·检查所提供的文件类型
·创建一个随机文件名
·将文件写入硬盘
·处理所有错误,如果一切顺利返回成功消息
第一步,我们定义处理程序:
- funcuploadFileHandler()http.HandlerFunc{
- returnhttp.HandlerFunc(func(whttp.ResponseWriter,r*http.Request){
然后,我们使用http.MaxBytesReader验证文件大小,当文件大小大于设定值时它将返回一个错误。错误将被一个助手程序renderError进行处理,它返回错误信息以及对应的HTTP状态码。
- r.Body=http.MaxBytesReader(w,r.Body,maxUploadSize)
- iferr:=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")
- iferr!=nil{
- renderError(w,"INVALID_FILE",http.StatusBadRequest)
- return
- }
- deferfile.Close()
- fileBytes,err:=ioutil.ReadAll(file)
- iferr!=nil{
- renderError(w,"INVALID_FILE",http.StatusBadRequest)
- return
- }
现在我们成功的验证了文件的大小,并读取了文件,接下来我们该检验文件的类型了。一种廉价但是并不安全的方式,只检查文件扩展名,并相信用户没有改变它,但是对于一个正式的项目来说并不应该这么做。
幸运的是,Go标准库提供给我们一个Http.DetectConntectType函数,这个函数基于mimesniff算法,祝需要读取文件的512个字节就能够判断文件的类型。
- iletype:=http.DetectContentType(fileBytes)
- iffiletype!="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)
- iferr!=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)
- iferr!=nil{
- renderError(w,"CANT_WRITE_FILE",http.StatusInternalServerError)
- return
- }
- defernewFile.Close()
- if_,err:=newFile.Write(fileBytes);err!=nil{
- renderError(w,"CANT_WRITE_FILE",http.StatusInternalServerError)
- return
- }
- w.Write([]byte("SUCCESS"))
这样就可以了。你可对这个简单的例子进行测试,使用虚拟的文件上传HTML页面,cURL或工具例如postman。
本文内容总结:2018年02月08日10:07:13冷月醉雪阅读数:346标签:golangHTTP文件上传更多,
原文链接:https://www.cnblogs.com/williamjie/p/9667270.html