ICode9

精准搜索请尝试: 精确搜索
首页 > 其他分享> 文章详细

Golang仿云盘项目-3.2 云存储系统之持久化

2022-07-15 21:34:15  阅读:224  来源: 互联网

标签:nil err 云盘 Golang tf 3.2 file mysql go


本文来自博客园,作者:Arway,转载请注明原文链接:https://www.cnblogs.com/cenjw/p/16478717.html

项目结构

.
├── db
│   ├── file.go
│   └── mysql
│       └── conn.go
├── doc
│   └── 建表语句.sql
├── go.mod
├── go.sum
├── handler
│   └── handler.go
├── main.go
├── meta
│   └── filemeta.go
├── static
│   └── view
│       └── index.html
└── util
    └── util.go

创建表

create database fileserver;
use fileserver;
CREATE TABLE `tbl_file` ( 
    `id` int(11) NOT NULL AUTO_INCREMENT,
    `file_sha1` char(40) NOT NULL DEFAULT '' COMMENT '文件hash',
    `file_name` varchar(256) NOT NULL DEFAULT '' COMMENT '文件名',
    `file_size` bigint(20) DEFAULT '0' COMMENT '文件大小',
    `file_addr` varchar(1024) NOT NULL DEFAULT '' COMMENT '文件存储位置',
    `create_at` datetime DEFAULT NOW() COMMENT '创建日期',
    `update_at` datetime DEFAULT NOW() on update current_timestamp() COMMENT '更新日期',
    `status` int(11) NOT NULL DEFAULT '0' COMMENT '状态(可用|禁用|已删除等状态)',
    `ext1` int(11) DEFAULT '0' COMMENT '备用字段1',
    `ext2` text COMMENT '备用字段2',
    PRIMARY KEY (`id`),
    UNIQUE KEY `idx_file_hash` (`file_sha1`),
    KEY `idx_status` (`status`)
) ENGINE=InnoDB DEFAULT CHARSET=utf8;

连接mysql

db/mysql/conn.go

点击查看代码
package mysql

import (
	"database/sql"
	"log"

	_ "github.com/go-sql-driver/mysql"  // 导入mysql驱动
)

// 声明mysql连接对象
var db *sql.DB

func init() {
	db, _ = sql.Open("mysql", "root:123456@tcp(127.0.0.1:3307)/fileserver?charset=utf8")
	db.SetConnMaxIdleTime(1000)
	err := db.Ping()  // test connection
	if err != nil {
		log.Fatal("Failed to connect to mysql, err: " + err.Error())
	}
}

// DBConn返回数据库连接对象
func DBConn() *sql.DB {
	return db
}

保存meta到mysql

文件上传完后,保存文件元信息到mysql

db/file.go

点击查看代码
// OnFileUploadOK: 文件上传完成,保存meta到数据库
func OnFileUploadOK(fsha1, filename, fileaddr string, filesize int64) bool {
	stmt, err := mydb.DBConn().Prepare(
		"insert ignore into tbll_file(`file_sha1`, `file_name`, `file_size`, " +
			"`file_addr`, `status`)values(?,?,?,?,1)")
	if err != nil {
		fmt.Println("Failed to prepare statement, err: " + err.Error())
		return false
	}

	defer stmt.Close()

	ret, err := stmt.Exec(fsha1, filename, filesize, fileaddr)
	if err != nil {
		fmt.Println(err.Error())
		return false
	}

	// 判断是否已经插入过相同fsha1的记录, 插入相同的会直接忽略
	if rf, err := ret.RowsAffected(); nil == err {
		if rf <= 0 { // sql 执行成功了,但没有产生新的记录,抛个warning
			fmt.Printf("File with hash: %s has been upload before", fsha1)
		}
		return true
	}
	return false
}

image

修改新增/更新文件元信息接口

meta/filemeta.go

// UpdateFileMetaDB: 新增/更新文件元信息到数据库
func UpdateFileMetaToDB(fm FileMeta) bool {
	return mydb.OnFileUploadOK(fm.FileSha1, fm.FileName, fm.Location, fm.FileSize)
}

handler/handler.go

// UploadHandler: 文件上传接口
func UploadHandler(w http.ResponseWriter, r *http.Request) {
	...
	else if r.Method == "POST" {
		...
		// meta.UpdateFileMeta(fileMeta)
		// 持久化到数据库
		_ = meta.UpdateFileMetaToDB(fileMeta)
		...

修改文件元信息查询接口

db/file.go

点击查看代码
func GetFileMeta(fhash string) (*TableFile, error) {
	stmt, err := mydb.DBConn().Prepare(
		"SELECT file_sha1, file_name, file_addr, file_size "+
		"FROM tbll_file where file_sha1=? limit 1")
	if err != nil {
		fmt.Println(err.Error())
		return nil, err
	}
	defer stmt.Close()

	tf := TableFile{}
	// Scan可以把数据库取出的字段值赋值给指定的数据结构
	err = stmt.QueryRow(fhash).Scan(&tf.FileSha1, &tf.FileName, &tf.FileAddr, &tf.FileSize)
	if err != nil {
		fmt.Println(err.Error())
		return nil, err
	}

	return &tf, nil
}

``
meta/filemeta.go

// GetFileMetaDB:从mysql获取元信息
func GetFileMetaFromDB(fhash string) (FileMeta, error) {
	tf, err := mydb.GetFileMeta(fhash)
	if err != nil {
		return FileMeta{}, err
	}

	fm := FileMeta{
		FileSha1: tf.FileSha1,
		FileName: tf.FileName.String,
		Location: tf.FileAddr.String,
		FileSize: tf.FileSize.Int64,
	}
	return fm, nil
}

handler/handler.go

// GetFileMetaHandler:通过文件sha1值获取文件元信息的接口
func GetFileMetaHandler(w http.ResponseWriter, r *http.Request) {
	...
	// fm := meta.GetFileMeta(fh)
	fm, err := meta.GetFileMetaFromDB(fh)
	if err != nil {
		w.WriteHeader(http.StatusInternalServerError)
	}
	...

测试:
http://localhost:8080/file/meta?filehash=1ce11ed4a3f0ebae4d78e0b66faf32ecc2c82ea7

标签:nil,err,云盘,Golang,tf,3.2,file,mysql,go
来源: https://www.cnblogs.com/cenjw/p/16478717.html

本站声明: 1. iCode9 技术分享网(下文简称本站)提供的所有内容,仅供技术学习、探讨和分享;
2. 关于本站的所有留言、评论、转载及引用,纯属内容发起人的个人观点,与本站观点和立场无关;
3. 关于本站的所有言论和文字,纯属内容发起人的个人观点,与本站观点和立场无关;
4. 本站文章均是网友提供,不完全保证技术分享内容的完整性、准确性、时效性、风险性和版权归属;如您发现该文章侵犯了您的权益,可联系我们第一时间进行删除;
5. 本站为非盈利性的个人网站,所有内容不会用来进行牟利,也不会利用任何形式的广告来间接获益,纯粹是为了广大技术爱好者提供技术内容和技术思想的分享性交流网站。

专注分享技术,共同学习,共同进步。侵权联系[81616952@qq.com]

Copyright (C)ICode9.com, All Rights Reserved.

ICode9版权所有