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  }