通过FormFile上传文件进行判断
导出文件(以".xlsx类型的Excel为例")及前端如何接收,请参考https://blog.csdn.net/fbbqt/article/details/105792435
获取当前文件的全路径及文件名:
package main
import (
"fmt"
"path"
"runtime"
)
func main() {
_, fullFilename, _, _ := runtime.Caller(0)
fmt.Println(fullFilename)
var filename string
filename = path.Base(fullFilename)
fmt.Println("filename=", filename)
}
//上传多文件
ctx.Request.MultipartForm
//上传单文件
ctx.Request.FormFile("file")
//file
是文件名
package demo
// 多包引入,每包独占一行
import (
"github.com/bilibili/kratos/pkg/log"
bm "github.com/bilibili/kratos/pkg/net/http/blademaster"
"io"
"os"
"strings"
)
type Sizer interface {
Size() int64
}
type Importdata struct {
Remarks string `json:"remarks"` //备注
}
func UpFile(ctx *bm.Context) error {
//通过FormFile上传单文件
file, handler, err := ctx.Request.FormFile("file")
if err != nil {
msg := "获取上传文件错误:" + err.Error()
fmt.Fprintf(ctx.Writer, msg)
return
}
defer file.Close()
//
//限制上传文件的大小
if fileSizer, ok := file.(Sizer); ok {
fileSize := fileSizer.Size() / (1024 * 1024)// 1024 * 1024是1M
fmt.Println("上传文件的大小为: %d", fileSize, handler.Filename)
if fileSize > 100 {
msg := "获取上传文件错误:文件大小超出100M"
fmt.Fprintf(ctx.Writer, msg)
return
}
}
//
//判断上传文件的文件后缀名,该文件刚上传,还在内存中
index := strings.LastIndex(header.Filename, ".")
if index < 0 {
fmt.println("cccccccccccccccccccc", index)
}
subfix := header.Filename[index:]
if subfix != ".xlsx" {
fmt.println("xxxxxxxxxxxx", subfix)
}
fmt.println("vvvvvvvvvvvvvvvvv", subfix)
//
//把文件保存下来
fileName:="../import.xlsx"
saveFile, err := os.OpenFile(fileName, os.O_CREATE|os.O_WRONLY, 0755)
defer saveFile.Close()
if err != nil {
log.Error("error(%v)(%v)", err, fileName)
return err
}
_, _ = io.Copy(saveFile, file)
//defer os.Remove(fileName) //这句话是删除保存的文件
//判断已保存文件的后缀 .xlsx 该文件已保存到本地
//fmt.Println("文件后缀:",path.Ext(fileName)
if path.Ext(fileName) != ".xlsx"{
fmt.println("111111111111111111")
}else {
fmt.println("2222222222222222222")
}
///
//第一种方法:从EXCEL中取值
var mySlice [][][]string
var value string
mySlice, err = xlFile.ToSlice()
value = mySlice[0][0][0] //Excel中具体单元格的内容
for k,v:=range mySlice{
//k代表Excel中有多少个Sheet表
fmt.Println("''''''''''''''',,,,,,,,,,,,,'''''''''''''''",k)
m代表单个Sheet中有多少行
for m,n:=range v{
fmt.Println("/,,,,,,",m)
for i,j:=range n{
//i代表每一行有多少列
fmt.Println(",,,,,,,,,,,,,",j)
}
}
}
fmt.Println("zzzzzzzzzzzz",value)
/
//第二种方法:从EXCEL中取值
for _, sheet := range xlFile.Sheets {
log.Info("Sheet Name: %s\n", sheet.Name)
fmt.Println(sheet)
imdata := Importdata{}
//若有标题行,则i=0时就是标题行
for i := 0; i < sheet.MaxRow; i++ {
for j := 0; j < sheet.MaxCol; j++ {
fmt.Println(sheet.Cell(i, j))
switch j {
case 0:
imdata.Remarks = fmt.Sprintf("%s", sheet.Cell(i, j))
}
}
}
}
///
return nil
}
gorm使用事务操作MySQL
要在事务中执行一组操作,一般流程如下:
// 开始事务
tx := db.Begin()
// 在事务中做一些数据库操作(从这开始在事务中使用'tx',而不是'db')
tx.Create(...)
// ...
// 发生错误时回滚事务
tx.Rollback()
// 或提交事务
tx.Commit()
一个具体的demo:
package demo
// 多包引入,每包独占一行
import (
"log"
"github.com/jinzhu/gorm"
)
func Demo(db *gorm.DB) err {
//开启事务
tx := db.Begin() // 注意,一旦你在一个事务中,使用tx作为数据库句柄
//函数完成,有错就回滚
//使用defer,则tx.Rollback()就只需要写一次,而不用每个错误都写一次。具体逻辑的写法就跟没有事务的写法一样了。
defer func() {
if e != err_code.Success{
log.Error("操作撤销", e)
tx.Rollback()
}
}()
//TODO 在事务中使用tx对数据库做操作
// ...
//以上所有操作执行都没有错误就提交
tx.Commit()
return nil
}