前端将一个100多M的视频文件切片后使用websocket发送给后端,后端(Go语言)将接收到的数据保留到磁盘上.
接下来发现发后端接受完数据后,本地播放器(不是HTML或Flash播放器)无法正常播放该视频文件,但播放上传之前的原视频文件则正常.
原视频文件和后端接收后保存到磁盘上的视频文件,大小相同(能精确到字节数,是不是能说明传输过程中数据没丢?)
但是对原视频和后端接受到的视频进行MD5检查,MD5值不一样.
我感觉是后端处理数据的时候出现了问题,有没有遇到过类似问题的同学?
[更新:]
下了一个1M以下的视频文件进行上传,发现一切正常.
又上传了11M大小的PDF文件,问题出现,两个文件的字节数相等,但MD5不等.
推测是js的代码有问题,可能是切片的时候应该严格按照字节来切.
(下面js代码中,最后一次slice的范围会超过文件的大小)
下面是部分核心代码:
upload.js
function upload() {
var slicesize = 1024 * 1024 * 5;
var file = document.getElementById("file").files[0];
var ws = new WebSocket("ws://127.0.0.1:8080/file");
var startsize = 0;
var endsize = 0;
var count = 0;
ws.onopen = function () {
console.log("成功连接到服务器");
ws.send(file.name);
console.log("size : ", file.size);
console.log("name size : ", file.name.length)
};
ws.onmessage = function (resp) {
//console.log("收到来自服务器的信息: ", resp.data);
if (resp.data) {
var sent = parseInt(resp.data);
var percent = sent / file.size * 100;
//console.log("percent:", percent, "%");
$('#progress').attr("style", "width: " + percent.toFixed(2) + "%");
$('#progress').text(percent.toFixed(2) + "%");
if (count == 0) {
ws.send(file.size);
count++
}
if (endsize < file.size) {
console.log("test");
startsize = endsize;
endsize += slicesize;
var blob = file.slice(startsize, endsize);
var reader = new FileReader();
reader.readAsArrayBuffer(blob);
reader.onload = function loaded(event) {
var arrayBuffer = event.target.result;
ws.send(arrayBuffer);
console.log("发送切片");
arrayBuffer = null;
}
} else {
//console.log("已发送: ", endsize);
startSize = endSize = 0;
//ws.send("~");
//console.log("全部发送完成!")
}
}
};
ws.onclose = function () {
console.log("成功关闭了连接");
loadMovie()
}
}
upload.go
func UploadFile(ws *websocket.Conn) {
var err error
var count int
var filename string
var filesize int
var savepath string
recData := bytes.NewBuffer([]byte{})
for {
var receive []byte
if err = websocket.Message.Receive(ws, &receive); err != nil {
log.Fatal(err)
break
}
if count == 1 {
filesize, err = strconv.Atoi(string(receive))
fmt.Println("文件大小: ", filesize)
} else if count == 0 {
filename = string(receive)
fmt.Println("文件名为: ", filename)
} else {
recData.Write(receive)
}
count++
sent := strconv.Itoa(len(recData.Bytes()))
//fmt.Println("sent:", sent)
//fmt.Println("本次接受到的文件长度为: ", len(receive))
//fmt.Println("当前文件总长度: ", len(recData.Bytes()))
if err = websocket.Message.Send(ws, sent); err != nil {
log.Fatal(err)
break
}
if len(recData.Bytes()) == filesize && sent != "0" {
break
}
}
wd, err := os.Getwd()
if err != nil {
log.Fatal(err)
}
savepath = path.Join(wd, "static", "upload")
movie := Movie{
Name: filename,
Path: savepath,
Size: filesize,
Time: time.Now().Format("2006-01-02 15:04:05"),
}
fp, err := os.Create(path.Join(savepath, movie.Time + movie.Name))
if err != nil {
log.Fatal(err)
}
defer fp.Close()
fmt.Println("文件总大小: ", len(recData.Bytes()))
recData.WriteTo(fp)
}
另外附上前几天提问的另外一个问题给有需要的同学,同一份代码
无法控制Websocket的send和receive事件
问题找到啦, 自己来解答下.
js代码没问题,问题出现在Go这个包上 a bug in the x/net/websocket package
我用github.com/gorilla/websocket替换掉它就OK了.