实现文件秒传
Posted 旧时星空
tags:
篇首语:本文由小常识网(cha138.com)小编为大家整理,主要介绍了实现文件秒传相关的知识,希望对你有一定的参考价值。
实现文件秒传
文件的校验值计算
校验算法类型 校验码长度
1.CRC 4/8字节 计算效率高但安全性较低 传输数据的校验
2.MD5 16个字节 中等 文件校验和数据签名
3.SHA1 20个字节 安全性高 文件校验和数据签名
秒传原理
场景
1.用户上传
2.离线下载
3.好友分享
关键点
1.文件的Hash值(MD5,Sha1)
每次文件上传到云存储服务,会自动计算文件的HASH值,下一次用户上传,只要Hash值相同就可以省区重复上传,客户端计算文件Hash值传到云端进行对比才可以实现秒传
2.用户文件的关联
建立唯一文件表用于存储唯一的文件的信息,而用户文件表存储每个用户的文件的信息,包括重复文件
文件秒传服务架构
如图
1.用户上传文件到上传server
2.上传server将文件存储到本地
3.调用Hash计算文件Hash值
4.将文件信息存储到唯一文件表
5.将文件信息关联到用户文件表
如果计算出文件Hash值比对成功则减少上传实现秒传
用户文件表结构
在db/下创建db/userFile,并创建用户文件结构体和用户文件表的更新
import (
mydb "rgo/src/db/mysql"
"time"
)
//用户文件表的结构体
type UserFile struct
UserName string
FileHash string
FileName string
FileSize int64
UploadAt string
LastUpdated string
//更新用户文件表
func OnUserFileUploadFinished(username,filehash,filename string,filesize int64)bool
stmt,err:=mydb.DBConn().Prepare("" +
"insert ignore into tbl_user_file(`user_name`,`file_sha1`,`file_name`,"+
"`file_size`,`upload_at`)values(?,?,?,?,?)")
if err!=nil
return false
defer stmt.Close()
_,err=stmt.Exec(username,filehash,filename,filesize,time.Now())
if err!=nil
return false
return true
在handler/handler.go的UploadHandler中修改
//更新用户文件表记录
r.ParseForm()
username := r.Form.Get("username")
suc := dblayer.OnUserFileUploadFinished(username, fileMeta.FileShal,
fileMeta.FileName, fileMeta.FileSize)
if suc
http.Redirect(w, r, "/file/upload/suc", http.StatusFound)
else
w.Write([]byte("Upload Failed"))
db/userFile下创建函数
//批量获取用户文件信息
func QueryUserFileMetas(username string,limit int)([]UserFile,error)
stmt,err:=mydb.DBConn().Prepare(
"select file_sha1,file_name,file_size,upload_at,last_update from"+
"tbl_user_file where user_name=? limit ?")
if err!=nil
return nil,err
defer stmt.Close()
rows,err:=stmt.Query(username,limit)
if err!=nil
return nil,err
var userFiles []UserFile
for rows.Next()//从数据库查找的表中将文件信息复制到[]UserFile作为返回
ufile:=UserFile
err=rows.Scan(&ufile.FileHash,&ufile.FileName,&ufile.FileSize,
&ufile.UploadAt,&ufile.LastUpdated)
if err!=nil
fmt.Println(err.Error())
break
userFiles=append(userFiles,ufile)
return userFiles,nil
在handler/handler.go修改接口
//查询批量的文件元信息
func FileQueryHandler(w http.ResponseWriter,r*http.Request)
r.ParseForm()
limitCnt,_:=strconv.Atoi(r.Form.Get("limit"))
username:=r.Form.Get("username")
userFiles,err:=dblayer.QueryUserFileMetas(username,limitCnt)
if err!=nil
w.WriteHeader(http.StatusInternalServerError)
return
data,err:=json.Marshal(userFiles)
if err!=nil
w.WriteHeader(http.StatusInternalServerError)
return
w.Write(data)
修改后效果,可以显示文件Hash值,文件名等
在handler/handler.go中编写
//尝试秒传接口
func TryFastUploadHandler(w http.ResponseWriter,r*http.Request)
r.ParseForm()
//1.解析请求参数
username:=r.Form.Get("username")
filehash:=r.Form.Get("filehash")
filename:=r.Form.Get("filename")
filesize,_:=strconv.Atoi(r.Form.Get("filesize"))
//从文件表中查询相同hash文件记录
fileMeta,err:=meta.GetFileMetaDB(filehash)
if err!=nil
fmt.Println(err.Error())
w.WriteHeader(http.StatusInternalServerError)
return
//查找不到记录则返回秒传失败
if fileMeta==nil
resp:=util.RespMsg
Code:-1,
Msg:"秒传失败,请访问普通上传接口",
w.Write(resp.JSONBytes())
return
//上传文过件则将文件信息写入用户文件表,返回成功
suc:=dblayer.OnUserFileUploadFinished(username,filehash,filename,int64(filesize))
if suc
resp:=util.RespMsg
Code:0,
Msg:"秒传成功",
w.Write(resp.JSONBytes())
return
else
resp:=util.RespMsg
Code:-2,
Msg:"秒传失败,请稍后重试",
w.Write(resp.JSONBytes())
return
以上是关于实现文件秒传的主要内容,如果未能解决你的问题,请参考以下文章