vue+golang上传微信头像

news2024/11/18 13:30:57

<button class="avatar" open-type="chooseAvatar" @chooseavatar="onChooseAvatar">
							<image :src="avatarUrl" class="avatar-img"></image>
						</button>
// 微信头像修改
			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
}

本文来自互联网用户投稿,该文观点仅代表作者本人,不代表本站立场。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如若转载,请注明出处:http://www.coloradmin.cn/o/1139695.html

如若内容造成侵权/违法违规/事实不符,请联系多彩编程网进行投诉反馈,一经查实,立即删除!

相关文章

排查一次类加载导致的OOM

问题背景 线上收到异常告警 查看监控发现应用从启动后metaspace的占用就一直在增长&#xff0c;增长到一定限制后&#xff0c;pod重启 排查过程 metaspace存储的是类的结构信息&#xff0c;一直在增长基本上是因为类一直被重复加载&#xff0c;无法被卸载掉 给应用加上启动参…

Kubernetes学习01

一、Kubernetes是什么 Kubernetes是容器集群管理系统&#xff0c;是一个开源的平台&#xff0c;可以实现容器集群的自动化部署、自动扩缩容、维护等功能。Kubernetes是谷歌开源的容器管理集群管理系统&#xff0c;是Google多年大规模容器管理技术Borg的开源版本。 它可以在物…

MySQL查询今日、昨日、最近七天的数据

查询今日数据 sql语句&#xff1a; SELECT * FROM short_oper_log WHERE to_days(login_time) to_days(now());运行结果&#xff1a; 查询昨日数据 sql语句&#xff1a; SELECT * FROM short_oper_log WHERE DATEDIFF(login_time,NOW()) -1;运行结果&#xff1a; 额外…

【瑞幸咖啡小程序-同盾】

需要联系主页V 瑞幸咖啡小程序 登入需要过同盾滑块下单需要balckbox参数 测试 过滑块 登入发短信

一场马拉松沸腾一座城 | 2023天津马拉松亲历记

点击文末“阅读原文”即可参与节目互动 剪辑、音频 / 卷圈 运营 / SandLiu 卷圈 监制 / 姝琦 封面 / 姝琦Midjourney 产品统筹 / bobo 场地支持 / 声湃轩北京录音间 津津乐道的三位主播都参与了 10.15 的天津马拉松并顺利完赛&#xff0c;比赛的当天&#xff0c;半个公司…

Talk | 纽约州立宾汉姆顿大学博士生丁琰:开放环境中机器人的任务与动作规划

本期为TechBeat人工智能社区第541期线上Talk。 北京时间10月26日&#xff08;周四&#xff09;20:00&#xff0c;纽约州立宾汉姆顿大学博士生—丁琰的Talk已准时在TechBeat人工智能社区开播&#xff01; 他与大家分享的主题是: “开放环境中机器人的任务与动作规划”&#xff0…

​ iOS自动混淆测试处理笔记

1 打开 ipa&#xff0c;导出ipa 路径和配置文件路径会自动填充 ​ 2 点击 开始自动混淆测试处理 自动混淆测试是针对 oc 类和oc方法这两个模块进行自动混淆ipa&#xff0c;并ipa安装到设备中运行&#xff0c;通过检测运行ipa包是否崩溃&#xff0c;来对oc类和oc方法进行筛选。…

高三高考免费试卷真题押题知识点合集

发表于安徽 温馨提示&#xff1a;有需要的真题试卷可联系本人&#xff0c;百卷内上免费资源。 感觉有用的下方三连&#xff0c;谢谢 ​ 。 免费版卷有6-60卷每卷平均4-30页 高三免费高三地理高三英语高三化学高三物理高三语文高三历史高三政治高三数学高三生物 付费版卷有1…

Linux文件描述符和打开文件之间的关系

简介 文件描述符和打开的文件之间似乎呈现出一一对应的关系。然而&#xff0c;实际并非如此。多个文件描述符指向同一打开文件&#xff0c;这既有可能&#xff0c;也属必要。这些文件描述符可在相同或不同的进程中打开。 要理解具体情况如何&#xff0c;需要查看由内核维护的…

安防监控项目---环境配置

文章目录 前言一、硬件平台二、软件平台三、开发环境配置流程总结 前言 书接上期&#xff0c;在这里呢还是需要强调一下项目环境的重要性&#xff0c;不论是在本次项目开发或者是在未来的项目开发中移植是非常重要的一项内容&#xff0c;作为开发者而言&#xff0c;需要考虑移…

拒绝拖延,从我做起!

拒绝拖延&#xff0c;从我做起&#xff01; 如果有一件事&#xff0c;对你的未来很重要&#xff0c;千万不要说等以后再做&#xff0c;这是无限拖延的借口【等有时间再做】的真正含义是&#xff0c;闲得无聊再去做&#xff0c;意味着事情即不重要也不紧急该做的重要事情不做&a…

Qt扫盲-QFontInfo理论

QFontInfo理论 一、概述二、创建QFontInfo对象 一、概述 QFontInfo类提供了关于字体的一般信息&#xff0c;包括是否是加粗、是否是斜体、字体大小、字体名称等等&#xff0c;使用也非常简单&#xff0c;其实就是一个属性查询类而已。 QFontInfo类提供了与QFont相同的访问函数…

交叉熵函数和KL散度函数

交叉熵函数&#xff08;Cross-Entropy Function&#xff09;和KL散度函数&#xff08;Kullback-Leibler Divergence Function&#xff09;都是用来度量两个概率分布之间的差异或相似性的数学函数。它们通常用于概率分布的比较&#xff0c;尤其在信息论和机器学习领域中。 交叉熵…

海南三亚摩托车三维扫描尺寸测绘机车零配件改装逆向抄数3D打印手板-CASAIM

在摩托车制造过程中&#xff0c;摩托车的曲面多&#xff0c;尺寸大&#xff0c;传统的测量方式通过千分尺及三坐标测量仪进行测量&#xff0c;存在部分位置无法精确测量和效率相对比较低等问题&#xff0c;难以快速完成大尺寸结构复杂的零部件三维数据重建。 而借助CASAIM三维…

49个过程背诵方法

五大过程组&#xff1a;启规执监收 需要死记住&#xff0c;五个比较好记按照顺序启动规划执行监控结束 十大过程&#xff1a;整范进&#xff0c;成质源&#xff0c;疯&#xff08;风&#xff09;狗&#xff08;沟&#xff09;踩&#xff08;采&#xff09;人 过程数量&#x…

在线客服系统源码全端通吃版+完全开源可二开 带完整搭建教程

随着互联网的快速发展&#xff0c;在线客服系统已经成为企业与客户沟通的重要工具。然而&#xff0c;市面上的在线客服系统往往存在限制多、成本高等问题。今天罗峰给大家介绍一种在线客服系统源码全端通吃版&#xff0c;并附带完整的搭建教程。 在线客服系统源码可以为企业提供…

电脑自动关机是什么原因?解决方案全解析!

电脑自动关机是一个令人头疼的问题&#xff0c;它可能由多种原因引起&#xff0c;从硬件故障到软件配置错误。在这篇文章中&#xff0c;我们将深入探讨电脑自动关机是什么原因&#xff0c;并提供三种常见问题的解决方法。无论您是电脑新手还是有经验的用户&#xff0c;都可以从…

Cesium 展示——一键控制所有 label 的显隐

文章目录 需求分析需求 实现一键控制所有 label 的显隐 分析 步骤如下: 获取场景中所有的实体(entities)。 遍历所有实体,获取实体中的label对象。 设置 label 的 show 属性为 false 或 true,以控制其显隐。 具体实现代码如下: var entities = viewer.entities; //…

UE4 使用材质后期 制作玻璃有雨效果

效果展示&#xff0c;其实这是一个动画效果 以上为所有逻辑 拿到TexCoord给到Panner&#xff0c;Time和Speed都是通过下面计算而来&#xff0c;后面讲&#xff0c;再拿到时间和速度值过后&#xff0c;加上扰动值&#xff0c;最后取G值&#xff0c;因为雨事从上而下的动&#xf…

1465. 切割后面积最大的蛋糕 : 为何仅需处理相邻切割位(多语言题解)

题目描述 这是 LeetCode 上的 「1465. 切割后面积最大的蛋糕」 &#xff0c;难度为 「中等」。 Tag : 「贪心」、「模拟」 矩形蛋糕的高度为 h 且宽度为 w&#xff0c;给你两个整数数组 horizontalCuts 和 verticalCuts&#xff0c;其中&#xff1a; horizontalCuts[i] 是从矩形…