个人分类: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