- <image :src="avatarUrl" class="avatar-img">image>
-
- // 微信头像修改
- onChooseAvatar(e) {
- this.uploadFile(e.detail.avatarUrl)
- },
- /* 上传头像转化格式*/
- uploadFile(avatarUrl){
- uni.uploadFile({
- url: this.fetch.fileUrl() + '/api/upload/uploadimages',//后台接口
- filePath: avatarUrl,// 上传图片 url
- name:'image',
- header: {
- 'content-type': 'multipart/form-data',
- 'token': uni.getStorageSync('token')
- }, // header 值
- success: res => {
- let obj = JSON.parse(res.data)
- console.log('obj', obj)
- if (obj. status == 'True') {
- this.avatarUrl = obj.data
- } else {
- this.common.toast(obj.msg)
- }
- },
- fail: e => {
- this.common.toast("上传失败")
- }
- });
- },
api后台接收文件
- /*
- * @Author: lmy
- * @Date: 2023-10-26 15:12:13
- * @LastEditors: lmy
- * @LastEditTime: 2023-10-27 10:40:14
- * @FilePath: \Project_UNI-APP_API\Main_Upload_Images.go
- * @Description: 正式版
- */
- package main
-
- import (
- "bytes"
- "io"
- "net/http"
- "path"
- "strings"
-
- "cntotal.com/sbjapi/xfileserviceapi"
- "cntotal.com/sbjbase/xjson"
- "cntotal.com/sbjlog"
- )
-
- // uploadImages 上传图片
- func uploadImages(w http.ResponseWriter, r *http.Request) {
- apiWriteHandler("", verifyUploadImages, &APIContext{Writer: w, Request: r, IsReadBody: true}, false)
- }
-
- // verifyUploadImages 上传图片
- func verifyUploadImages(a *APIContext) bool {
- defer func() {
- if err := recover(); err != nil {
- sbjlog.ExcLog("100", "[%s]verifyUploadImages-小程序登录:%s", a.Flag.Code, err)
- }
- }()
- uploadFile, handle, err := a.Request.FormFile("image")
- ext := strings.ToLower(path.Ext(handle.Filename))
- if ext != ".jpg" && ext != ".png" && ext != ".jpeg" {
- a.Resp.Msg = "只支持jpg/jpeg/png图片上传"
- return false
- }
- var buff = new(bytes.Buffer)
- _, _ = io.Copy(buff, uploadFile)
- buffByte := buff.Bytes()
- dataStr, err := xfileserviceapi.UploadTempFile(handle.Filename, &buffByte)
- if err != nil {
- sbjlog.Debug("xfileserviceapi.UploadTempFile 上传图片失败,图片名称:%v,err:%v ", handle.Filename, err)
- a.Resp.Msg = "上传图片失败"
- return false
- }
- returnData := xjson.JSONToMapString(dataStr)
- fileurl := returnData["fileurl"]
- if fileurl == "" {
- a.Resp.Msg = "上传图片失败"
- return false
- }
- a.Resp.Data = fileurl
- a.Resp.Msg = "上传图片成功"
- return true
- }
上传文件接口
- package main
-
- import (
- "net/http"
- "strings"
-
- "cntotal.com/sbjbase"
- "cntotal.com/sbjlog"
-
- systemdb "cntotal.com/ProjectDBLibrary/system/DB"
- "cntotal.com/sbjbase/xalgorithm"
- "cntotal.com/sbjbase/xjson"
- )
-
- // 上传临时文件
- func type23(w http.ResponseWriter, r *http.Request) {
- apiWriteHandler("23", verify23, &APIContext{Writer: w, Request: r})
- }
-
- // 上传临时文件
- func verify23(a *APIContext) bool {
- var err error
- fileName := a.WordData["fileName"]
- uploadType := a.WordData["uploadType"] // 上传方式 10=覆盖上传 | 为空代表非覆盖,生成随机文件名
- Tp := a.WordData["Tp"]
- CheckKey := a.WordData["CheckKey"]
- //检验CheckKey
- sCheckKey := xalgorithm.MD5ToUpper32(xalgorithm.MD5ToUpper32(xalgorithm.MD5ToUpper32(fileName + Tp)[:15]))
-
- if CheckKey != sCheckKey {
- a.Resp.Msg = "CheckKey 验证不通过"
- return false
- }
- //验证参数值
- if fileName == "" {
- a.Resp.Msg = "fileName临时文件名不能为空"
- return false
- }
- //写入文件日志
- var systemFileLog systemdb.SystemFileLog
- systemFileLog.Status = 10 // 状态 = 正常
- systemFileLog.EnvironmentType = runEnvironment // 环境变量
- systemFileLog.Pid = a.ProgramID // 上传程序ID
- systemFileLog.Type = 10 // 类型=上传
- systemFileLog.FileType = 40 // 文件类型 40=临时文件
- systemFileLog.IP = a.RequestIP // 上传IP
- //处理保存 文件属性
- fileProgramID := a.ProgramID //文件归属程序 (关系到文件的路径写入)
- if a.WordData["isProjectFile"] == "1" {
- fileProgramID = a.ProgramID / 100 * 100 //取整数 710020 / 100 = 710000
- }
- // 定义是否随机文件名 | 如果不是覆盖上传,则填充随机文件名
- randomName := uploadType != "10"
- // 获取保存文件路径信息
- saveFilePath := getPathWithTempFile(fileProgramID, fileName, randomName)
- systemFileLog.FilePath = saveFilePath.FilePath
- // systemFileLog.FilePath, _, filename, fileext = GetPathWithTempFile(fileProgramID, tempPath)
- if strings.Index(saveFilePath.FileName, ".") == 0 {
- a.Resp.Msg = "文件名格式不正确"
- return false
- }
- if indexStringArray(tempFileExt, saveFilePath.FileExt) == -1 {
- a.Resp.Msg = "不满足临时文件文件格式"
- return false
- }
- // 因为数据已经转为了base64 ,源文件大小 * 133% = 现在大小 。 所以当前大小 / 133% = 原文件大小
- // 提前判断的原因:在前面提前读取判断防止无效读取文件,避免流量损失
- if a.Request.ContentLength*3/4 > int64(tempFileSize) {
- a.Resp.Msg = "临时文件文件超出大小" + getMegabytesString(fileSize) + "限制"
- return false
- }
- // 读取数据保存到指定路径 | 并计算文件md5
- var tfMd5 string
- systemFileLog.FileLength, tfMd5, err = readBodyFileToPath(a.Request, systemFileLog.FilePath)
- if err != nil {
- sbjlog.Debug("verify23-readBodyFileToCacheDir Error:%s", err.Error())
- a.Resp.Msg = "读取上传文件出现异常"
- return false
- }
- // 写入临时文件上传日志
- sflid := systemdb.InsertSystemFileLog(systemFileLog)
- if sflid < 1 {
- a.Resp.Msg = "新增文件日志失败"
- return false
- }
- a.Resp.Data, _ = sbjbase.AESEncrypt(
- xjson.MapToJSON(
- map[string]interface{}{
- "fileid": sflid,
- "fileurl": fileHost + strings.TrimPrefix(systemFileLog.FilePath, "./"),
- "filemd5": tfMd5}),
- CheckKey[:16])
- return true
- }
上传临时文件方法
- // readBodyFileToCacheDir 读取传输的文件保存到缓存文件夹
- // 返回 临时存储地址,文件MD5,错误信息
- func readBodyFileToCacheDir(r *http.Request) (filepath string, filesize int, md5Str string, err error) {
- filepath = cacheFileDir + fmt.Sprintf("%s_%s.temp", time.Now().Format("20060102150405"), xstring.RandomString(12, ""))
- filesize, md5Str, err = readBodyFileToPath(r, filepath)
- return
- }
-
- // readBodyFileToPath 从Body中读取文件保存到指定路径
- func readBodyFileToPath(r *http.Request, filepath string) (filesize int, md5Str string, err error) {
- var f *os.File
- f, err = os.Create(filepath)
- if err != nil {
- return
- }
- defer f.Close()
- // 按照Base64 编码分块读取数据到文件 ? 问题:未到限定步长
- _, err = xbinary.Copy(f, r.Body, 32*1024, xbinary.EncodeBase64)
- if err != nil {
- return
- }
- // 重置一下位置
- f.Seek(0, 0)
- var file os.FileInfo
- file, err = f.Stat()
- if err != nil {
- return
- }
- filesize = int(file.Size())
- if filesize <= 0 {
- err = errors.New("文件内容为空")
- return
- }
- // 把文件重新读出来 分块进行 MD5
- md5Str, err = xalgorithm.MD5BlocksToUpper32(f, 32*1024, xalgorithm.EncodeHexLower)
- return
- }