代码拉取完成,页面将自动刷新
// @File : local.go
// @Author: JunLong.Liao&此处不应有BUG!
// @Date : 2021/5/26
// @slogan: 又是不想写代码的一天,神兽保佑,代码无BUG!
// ┏┓ ┏┓
// ┏┛┻━━━━━━┛┻┓
// ┃ ღ ┃
// ┃ ┳┛ ┗┳ ┃
// ┃ ┻ ┃
// ┗━┓ ┏━┛
// ┃ ┗━━━┓
// ┃ 神兽咆哮! ┣┓
// ┃ ┏┛
// ┗┓┓┏━━━┳┓┏┛
// ┃┫┫ ┃┫┫
// ┗┻┛ ┗┻┛
package CloudStorage
import (
"encoding/base64"
"errors"
"github.com/nfnt/resize"
"image"
"image/gif"
"image/jpeg"
"image/png"
"io"
"io/ioutil"
"log"
"math/rand"
"mime/multipart"
"os"
"path"
"regexp"
"strconv"
"strings"
"time"
)
type Local struct {
Path string `mapstructure:"path" json:"path" yaml:"path"` // 本地文件路径
}
// 本地上传
type LocalOSS interface {
IsFileExist(filename string) bool // 检查文件是否存在
UploadFile(file *multipart.FileHeader) (path, filename string, err error) // 上传文件
DeleteFile(key string) error // 删除文件
ImageClip(filename string, wi, hi, x0, y0, x1, y1, quality int) (Path, FileName string, err error) // 裁剪图片
ImageScale(filename string, width, height, quality int) (Path, FileName string, err error) // 缩略图
UploadFileByBase64(ImageContent string) (Path, Filename string, err error) // base64上传图片
}
// 实例本地上传
func NewLocalOSS(c *Local) LocalOSS {
return &Local{
Path: c.Path,
}
}
// @author: [wulala](https://github.com/water-gulugulu)
// @object: *LocalUpload
// @function: UploadFile
// @description: 上传文件
// @param: file *multipart.FileHeader
// @return: Path string
// @return: FileName string
// @return: err error
func (l *Local) UploadFile(file *multipart.FileHeader) (Path, FileName string, err error) {
// 读取文件后缀
ext := path.Ext(file.Filename)
// 读取文件名并加密
name := strings.TrimSuffix(file.Filename, ext)
name = MD5V([]byte(name))
// 拼接新文件名
filename := name + "_" + time.Now().Format("20060102150405") + ext
// 尝试创建此路径
mkdirErr := os.MkdirAll(l.Path, os.ModePerm)
if mkdirErr != nil {
return "", "", errors.New("function os.MkdirAll() Filed, err:" + mkdirErr.Error())
}
// 拼接路径和文件名
p := l.Path + "/" + filename
f, openError := file.Open() // 读取文件
if openError != nil {
return "", "", errors.New("function file.Open() Filed, err:" + openError.Error())
}
out, createErr := os.Create(p)
if createErr != nil {
return "", "", errors.New("function os.Create() Filed, err:" + createErr.Error())
}
defer func() {
_ = f.Close()
_ = out.Close()
}()
_, copyErr := io.Copy(out, f) // 传输(拷贝)文件
if copyErr != nil {
return "", "", errors.New("function io.Copy() Filed, err:" + copyErr.Error())
}
return p, filename, nil
}
// @author: [wulala](https://github.com/water-gulugulu)
// @object: *LocalUpload
// @function: DeleteFile
// @description: 删除文件
// @param: key string
// @return: error
func (l *Local) DeleteFile(key string) error {
p := l.Path + "/" + key
if strings.Contains(p, l.Path) {
if err := os.Remove(p); err != nil {
return errors.New("本地文件删除失败, err:" + err.Error())
}
}
return nil
}
// @author: [wulala](https://github.com/water-gulugulu)
// @author: [wulala](https://gitee.com/diunigedaxigua)
// @function: ClipFile
// @description: 图片裁剪
// @param: filename string 要裁剪的文件名,会和Local.Path拼接组成文件名
// @param: wi int 裁剪宽度,传0则默认裁剪宽度 如原图宽为100px x0:10 x1:90 那么成图宽为x1-x0=80px
// @param: hi int 裁剪高度,传0则默认裁剪高度 如原图高为100px y0:10 y1:90 那么成图高为y1-y0=80px
// @param: x0 int 裁剪宽坐标,从多少像素开始裁剪,如原图100px x0:10那么从10像素开始裁剪
// @param: y0 int 裁剪高坐标,从多少像素开始裁剪,如原图100px y0:10那么从10像素开始裁剪
// @param: x1 int 裁剪宽坐标,从x0开始到x1像素裁剪结束,如原图100px x0:10,x1:30那么从10像素开始裁剪到40像素结束
// @param: y1 int 裁剪高坐标,从y0开始到y1像素裁剪结束,如原图100px y0:10,y1:30那么从10像素开始裁剪到40像素结束
// @param: quality int 像素精度 百分比
// @return: Path string 文件访问路径(带文件名)
// @return: FileName string 文件名
// @return: err error 错误信息
func (l *Local) ImageClip(filename string, width, height, x0, y0, x1, y1, quality int) (Path, FileName string, err error) {
var in, out *os.File
// 打开文件
in, err = os.Open(l.Path + "/" + filename)
if err != nil {
log.Println(err)
return
}
// 替换文件名加上_small
FileName = strings.Replace(filename, ".", "_small.", 1)
Path = l.Path + "/" + FileName
out, err = os.Create(Path)
if err != nil {
log.Println(err)
return
}
defer func() {
_ = in.Close()
_ = out.Close()
if r := recover(); r != nil {
log.Println(r)
}
}()
var origin, canvas image.Image
var fm string
origin, fm, err = image.Decode(in)
if err != nil {
log.Println(err)
return
}
// 如果未设置宽高那么就默认截取后宽高,如果设置了宽高,那么计算最后截取剩下的宽高
if width == 0 || height == 0 {
width = origin.Bounds().Max.X
height = origin.Bounds().Max.Y
} else {
x1 += width // x1 加上最后要截取的宽度
y1 += height // y1 加上最后要截取的高度
// 如果大于原图宽度 那么就设置最大为原图宽度
if x1 > origin.Bounds().Max.X {
x1 = origin.Bounds().Max.X
}
// 如果大于原图高度 那么就设置最大为原图高度
if y1 > origin.Bounds().Max.Y {
y1 = origin.Bounds().Max.Y
}
}
canvas = origin
if quality == 0 {
quality = 100
}
// 图片处理
switch fm {
case "jpeg":
img := canvas.(*image.YCbCr)
subImg := img.SubImage(image.Rect(x0, y0, x1, y1)).(*image.YCbCr)
subImg2 := resize.Thumbnail(uint(width), uint(height), subImg, resize.Lanczos3)
err = jpeg.Encode(out, subImg2, &jpeg.Options{quality})
return
case "png":
switch canvas.(type) {
case *image.NRGBA:
img := canvas.(*image.NRGBA)
subImg := img.SubImage(image.Rect(x0, y0, x1, y1)).(*image.NRGBA)
subImg2 := resize.Thumbnail(uint(width), uint(height), subImg, resize.Lanczos3)
err = png.Encode(out, subImg2)
return
case *image.RGBA:
img := canvas.(*image.RGBA)
subImg := img.SubImage(image.Rect(x0, y0, x1, y1)).(*image.RGBA)
subImg2 := resize.Thumbnail(uint(width), uint(height), subImg, resize.Lanczos3)
err = png.Encode(out, subImg2)
return
}
case "gif":
img := canvas.(*image.Paletted)
subImg := img.SubImage(image.Rect(x0, y0, x1, y1)).(*image.Paletted)
subImg2 := resize.Thumbnail(uint(width), uint(height), subImg, resize.Lanczos3)
err = gif.Encode(out, subImg2, &gif.Options{})
return
// case "bmp":
// img := canvas.(*image.RGBA)
// subImg := img.SubImage(image.Rect(x0, y0, x1, y1)).(*image.RGBA)
// subImg2 := resize.Thumbnail(uint(width), uint(height), subImg, resize.Lanczos3)
// err = bmp.Encode(out, subImg2)
// return
default:
err = errors.New("ERROR FORMAT")
return
}
return
}
// @author: [wulala](https://github.com/water-gulugulu)
// @author: [wulala](https://gitee.com/diunigedaxigua)
// @function: ImageScale
// @description: 缩略图生成
// @param: filename string 要裁剪的文件名,会和Local.Path拼接组成文件名
// @param: width int 裁剪宽度,传0则默认裁剪宽度 如原图宽为100px x0:10 x1:90 那么成图宽为x1-x0=80px
// @param: height int 裁剪高度,传0则默认裁剪高度 如原图高为100px y0:10 y1:90 那么成图高为y1-y0=80px
// @param: quality int 像素精度 百分比
// @return: Path string 文件访问路径(带文件名)
// @return: FileName string 文件名
// @return: err error 错误信息
func (l *Local) ImageScale(filename string, width, height, quality int) (Path, FileName string, err error) {
var in, out *os.File
in, err = os.Open(l.Path + "/" + filename)
if err != nil {
log.Println(err)
return
}
// 替换文件名加上_small
FileName = strings.Replace(filename, ".", "_thumbnail.", 1)
Path = l.Path + "/" + FileName
out, err = os.Create(Path)
if err != nil {
log.Println(err)
return
}
defer func() {
_ = in.Close()
_ = out.Close()
if r := recover(); r != nil {
log.Println(r)
}
}()
origin, fm, err := image.Decode(in)
if err != nil {
log.Println(err)
return
}
if width == 0 || height == 0 {
width = origin.Bounds().Max.X
height = origin.Bounds().Max.Y
}
if quality == 0 {
quality = 100
}
canvas := resize.Thumbnail(uint(width), uint(height), origin, resize.Lanczos3)
switch fm {
case "jpeg":
err = jpeg.Encode(out, canvas, &jpeg.Options{quality})
case "png":
err = png.Encode(out, canvas)
case "gif":
err = gif.Encode(out, canvas, &gif.Options{})
// case "bmp": //被我注释掉的是x/image/bmp
// return w, h, bmp.Encode(out, canvas)
default:
err = errors.New("ERROR FORMAT")
}
return
}
// @author: [wulala](https://github.com/water-gulugulu)
// @author: [wulala](https://gitee.com/diunigedaxigua)
// @function: IsFileExist
// @description: 检查文件是否存在
// @param: filename string 要检查的文件名,会和Local.Path拼接组成文件名
// @return: bool true:存在,false:不存在
func (l *Local) IsFileExist(filename string) bool {
_, err := os.Stat(l.Path + "/" + filename)
if os.IsNotExist(err) {
return false
}
return true
}
// @author: [wulala](https://github.com/water-gulugulu)
// @author: [wulala](https://gitee.com/diunigedaxigua)
// @function: UploadFileByBase64
// @description: 上传base64保存到图片
// @param: ImageContent string 图片的base64编码字符串
// @return: Path string 文件访问路径(带文件名)
// @return: FileName string 文件名
// @return: err error 错误信息
func (l *Local) UploadFileByBase64(ImageContent string) (Path, Filename string, err error) {
b, _ := regexp.MatchString(`^data:\s*image\/(\w+);base64,`, ImageContent)
if !b {
return "", "", errors.New("图片为空")
}
re, _ := regexp.Compile(`^data:\s*image\/(\w+);base64,`)
// allData := re.FindAllSubmatch([]byte(ImageContent), 2)
// fileType := string(allData[0][1]) // png ,jpeg 后缀获取
// if len(fileType) == 0 {
// fileType = ".jpg"
// }
base64Str := re.ReplaceAllString(ImageContent, "")
curFileStr := strconv.FormatInt(time.Now().UnixNano(), 10)
r := rand.New(rand.NewSource(time.Now().UnixNano()))
n := r.Intn(99999)
name := MD5V([]byte(curFileStr + strconv.Itoa(n)))
// 拼接新文件名
filename := name + "_" + time.Now().Format("20060102150405") + ".jpg"
var file = l.Path + "/" + filename
byte, err := base64.StdEncoding.DecodeString(base64Str)
if err != nil {
return "", "", err
}
if err = ioutil.WriteFile(file, byte, 0777); err != nil {
return "", "", err
}
return l.Path + "/" + filename, filename, nil
}
此处可能存在不合适展示的内容,页面不予展示。您可通过相关编辑功能自查并修改。
如您确认内容无涉及 不当用语 / 纯广告导流 / 暴力 / 低俗色情 / 侵权 / 盗版 / 虚假 / 无价值内容或违法国家有关法律法规的内容,可点击提交进行申诉,我们将尽快为您处理。