github.com/insionng/yougam@v0.0.0-20170714101924-2bc18d833463/modules/apis/version2/UploadHandler.go (about) 1 package version2 2 3 import ( 4 "fmt" 5 "github.com/insionng/makross" 6 "github.com/insionng/makross/jwt" 7 "io" 8 "log" 9 "mime/multipart" 10 "os" 11 "path" 12 "strconv" 13 "strings" 14 "time" 15 "github.com/insionng/yougam/helper" 16 ) 17 18 type UploadError struct { 19 Error string `json:"error"` 20 } 21 22 type Files struct { 23 Files []string `json:"files"` 24 } 25 26 func PostUploadHandler(self *makross.Context) error { 27 var uploadError UploadError 28 uploadError.Error = "ErrServiceUnavailable" 29 var fz = new(Files) 30 31 parent := self.Args("parent").String() //格式 parent="topic:2",创建时id为0,须要服务端在前端完成提交流程后再进行二次修正操作 32 fmt.Println(parent) 33 34 //single file 35 uploadFile, serr := self.FormFile("uploadFile") 36 if serr != nil { 37 38 // Multipart form 39 form, merr := self.MultipartForm() 40 if merr != nil { 41 uploadError.Error = fmt.Sprintf("PostUploadHandler() self.FormFile() Error:(%v) and self.MultipartForm() Error:(%v)", serr, merr) 42 return self.JSON(uploadError) 43 } 44 45 files := form.File["uploadFiles"] 46 for _, file := range files { 47 // Source 48 srcFile, err := file.Open() 49 if err != nil { 50 uploadError.Error = fmt.Sprintf("PostUploadHandler() self.MultipartForm() file.Open() (%v)", err) 51 return self.JSON(uploadError) 52 } 53 defer srcFile.Close() 54 55 // Copy 56 fz, err = ioProcess(srcFile, file.Filename, fz, self) 57 if err != nil { 58 uploadError.Error = fmt.Sprintf("PostUploadHandler() ioProcess() Error:%v", err) 59 return self.JSON(uploadError) 60 } 61 } 62 if len(files) == len(fz.Files) { 63 return self.JSON(fz) 64 } 65 66 uploadError.Error = fmt.Sprintf("PostUploadHandler() self.FormFile() Error:%v", serr) 67 return self.JSON(uploadError) 68 } else { 69 srcFile, err := uploadFile.Open() 70 if err != nil { 71 uploadError.Error = "PostUploadHandler() uploadFile.Open() Errors" 72 return self.JSON(uploadError) 73 } 74 defer srcFile.Close() 75 76 // Copy 77 fz, err = ioProcess(srcFile, uploadFile.Filename, fz, self) 78 if err != nil { 79 uploadError.Error = fmt.Sprintf("PostUploadHandler() ioProcess() Error:%v", err) 80 return self.JSON(uploadError) 81 } 82 return self.JSON(fz) 83 } 84 85 } 86 87 func ioProcess(srcFile multipart.File, uploadFilename string, files *Files, self *makross.Context) (*Files, error) { 88 var uploadError UploadError 89 uploadError.Error = "ErrServiceUnavailable" 90 91 claims := jwt.GetMapClaims(self) 92 var IsSigned bool 93 var uid int64 94 if jwtUserId, okay := claims["UserId"].(float64); okay { 95 uid = int64(jwtUserId) 96 if uid <= 0 { 97 uploadError.Error = "尚未登录" 98 } 99 IsSigned = true 100 } 101 102 if !IsSigned { 103 return nil, self.JSON(uploadError) 104 } 105 106 targetFolder := helper.FileStorageDir + "file" 107 ext := strings.ToLower(path.Ext(uploadFilename)) 108 filename := helper.MD5(time.Now().String()) + ext 109 dirPath := fmt.Sprintf("%v/%v", targetFolder, fmt.Sprintf("%v/%v", uid, time.Now().Format("03/04/"))) 110 111 err := os.MkdirAll(dirPath, 0755) 112 if err != nil { 113 uploadError.Error = fmt.Sprintf("PostUploadHandler() ioProcess() os.MkdirAll() (%v)", err) 114 return nil, self.JSON(uploadError) 115 } 116 117 tempPath := dirPath + filename 118 f, err := os.OpenFile(tempPath, os.O_WRONLY|os.O_CREATE, 0755) 119 if err != nil { 120 uploadError.Error = fmt.Sprintf("PostUploadHandler() ioProcess() os.OpenFile() (%v)", err) 121 return nil, self.JSON(uploadError) 122 } 123 defer f.Close() 124 125 if _, err := io.Copy(f, srcFile); err != nil { 126 uploadError.Error = fmt.Sprintf("PostUploadHandler() ioProcess() io.Copy() (%v)", err) 127 return nil, self.JSON(uploadError) 128 } 129 if !(ext == ".png" || ext == ".jpg" || ext == ".jpeg" || ext == ".gif") { 130 filehash, _ := helper.Filehash(helper.URL2local(tempPath), nil) 131 fname := helper.EncryptHash(filehash+strconv.Itoa(int(uid)), nil) 132 finalPath := dirPath + fname + ext 133 134 if err := os.Rename(helper.URL2local(tempPath), helper.URL2local(finalPath)); err != nil { 135 log.Println("重命名文件发生错误:", err) 136 } else { 137 os.Remove(helper.URL2local(tempPath)) 138 } 139 if fhashed, _ := helper.Filehash(helper.URL2local(finalPath), nil); helper.ValidateHash(fname, fhashed+strconv.Itoa(int(uid))) { 140 s := fmt.Sprintf("/file/%v", finalPath[8:]) 141 files.Files = append(files.Files, s) 142 return files, nil 143 } else { 144 uploadError.Error = "PostUploadHandler() ioProcess() 校验文件不正确" 145 146 if e := os.Remove(helper.URL2local(finalPath)); e != nil { 147 log.Println(fmt.Sprintf("PostUploadHandler() ioProcess() 清除错误文件 %v 出错:%v", finalPath, e)) 148 } 149 150 return nil, self.JSON(uploadError) 151 } 152 } else { 153 154 inputFile := tempPath 155 outputFile := fmt.Sprintf("%s%v-%s", dirPath, uid, filename) 156 outputSize := "768x0" 157 outputAlign := "center" 158 background := "white" 159 staticPath := "./themes/" + helper.Theme() + "/static" 160 watermarkFile := staticPath + "/img/watermark.png" 161 162 //所有上传的图片都会被缩略处理 163 err = helper.Thumbnail("resize", inputFile, outputFile, outputSize, outputAlign, background) 164 if err != nil { 165 uploadError.Error = fmt.Sprintf("PostUploadHandler() ioProcess() 生成缩略图出错:%v", err) 166 if err := os.Remove(helper.URL2local(inputFile)); err != nil { 167 os.Remove(helper.URL2local(outputFile)) 168 uploadError.Error = fmt.Sprintf("PostUploadHandler() ioProcess() 删除缩略图出错:%v", err) 169 } 170 return nil, self.JSON(uploadError) 171 } else { 172 173 os.Remove(helper.URL2local(inputFile)) 174 175 helper.Watermark(watermarkFile, outputFile, outputFile, "SouthEast") 176 177 filehash, _ := helper.Filehash(helper.URL2local(outputFile), nil) 178 fname := helper.EncryptHash(filehash+strconv.Itoa(int(uid)), nil) 179 finalPath := dirPath + fname + ext 180 181 if err := os.Rename(helper.URL2local(outputFile), helper.URL2local(finalPath)); err != nil { 182 log.Println("重命名文件发生错误:", err) 183 } else { 184 os.Remove(helper.URL2local(outputFile)) 185 } 186 187 //文件权限校验 通过说明文件上传转换过程中没发生错误 188 //首先读取被操作文件的hash值 和 用户请求中的文件hash值 以及 用户当前id的string类型 进行验证 189 if fhashed, _ := helper.Filehash(helper.URL2local(finalPath), nil); helper.ValidateHash(fname, fhashed+strconv.Itoa(int(uid))) { 190 s := fmt.Sprintf("/file/%v", finalPath[8:]) 191 files.Files = append(files.Files, s) 192 return files, nil 193 } else { 194 uploadError.Error = "PostUploadHandler() ioProcess() 校验图片不正确" 195 if e := os.Remove(helper.URL2local(finalPath)); e != nil { 196 log.Println(fmt.Sprintf("PostUploadHandler() ioProcess() 清除错误文件 %v 出错:%v", finalPath, e)) 197 } 198 return nil, self.JSON(uploadError) 199 } 200 } 201 } 202 }