package main
import (
"fmt"
"io"
"os"
"strconv"
"time"
)
type MyCopy struct{}
func NewMyCopy() *MyCopy {
return new(MyCopy)
}
var last string = "/tmp/last.txt"
/**
* 功能:文件复制(支持断点续传)
* Seek(offset int64, whence int) (ret int64, err error) 表示设置当前光标的位置
* offset int,设置多个字节
* whence int,从哪开始 0->距离文件开头 1->当前位置 2->距离文件末尾
*
*/
func (c *MyCopy) CopyFile(dstFile, srcFile string) (int, error) {
src, err := os.Open(srcFile)
if err != nil {
fmt.Printf("open srcFile failed:%v\n", err)
return -1, err
}
dst, err := os.OpenFile(dstFile, os.O_CREATE|os.O_WRONLY, 0775)
if err != nil {
fmt.Printf("open dstFile failed:%v\n", err)
return -1, err
}
defer src.Close()
defer dst.Close()
lastPos := c.GetLastPosition()
var position int = 0
if lastPos > 0 {
src.Seek(int64(lastPos), io.SeekStart) //0
dst.Seek(int64(lastPos), io.SeekStart) //0
position = lastPos
}
fmt.Printf("当前读取位置为:%d\n", position)
var buf [128]byte
for {
/*if position == 512 {
fmt.Println("模拟中断传输")
break
}*/
count, err := src.Read(buf[:])
if err == io.EOF {
os.Remove(last) //删除记录内容
break
}
if err != nil {
fmt.Printf("read file context failed:%v\n", err)
break
}
position += count
fmt.Printf("copy cap:%d\r", position)
time.Sleep(100 * time.Millisecond) //模拟网络延迟
dst.Write(buf[:count])
c.WritePosition([]byte(fmt.Sprintf("%d", position)))
}
fmt.Println()
return position, nil
}
/*
* 获取上次断点位置
*/
func (c *MyCopy) GetLastPosition() int {
file, err := os.Open(last)
if err != nil {
return -1
}
defer file.Close()
var buf [128]byte
n, err := file.Read(buf[:])
if err != nil {
return -1
}
v, err := strconv.Atoi(string(buf[:n]))
if err != nil {
return -1
}
if n <= 0 {
return -1
}
return v
}
/**
* 写入当前读取到位置
*/
func (c *MyCopy) WritePosition(v []byte) {
//Write(b []byte) (n int, err error)
file, err := os.OpenFile(last, os.O_CREATE|os.O_TRUNC|os.O_WRONLY, 0666)
if err != nil {
fmt.Printf("write last position to failed:%v\n", err)
return
}
file.Write(v)
defer file.Close()
}
func main() {
c := NewMyCopy()
c.CopyFile("a.txt", "employer.go")
}
go文件断点续传(简易版本)
最新推荐文章于 2022-07-20 10:28:19 发布