【发布时间】:2013-12-15 23:42:36
【问题描述】:
我正在尝试在 html5/js 和节点中实现一个文件上传器,它以块的形式上传大文件。它非常适合单次上传。但是当我尝试在同一页面上再次上传时,它会进入一个无限循环,看起来它正在尝试一次重新上传上一次上传和新文件。
客户端.js
$('input').change(function() {
var file = this.files[0]
var fileSize = file.size
var fileName = file.name
// file size gate:
var fileSizeLimit = 15000000 // ~15mb
if (fileSize <= fileSizeLimit) {
// get preview blob
var windowURL = window.URL || window.webkitURL
var blobURL = windowURL.createObjectURL(this.files[0])
// render preview image
// render status progress
// set progress to 0
// read the file to server:
var reader = new FileReader()
console.log('new filereader init')
socket.emit('startSend', fileName, fileSize, entryID)
console.log('startSend emitted now for ' + fileName)
reader.onload = function(event) {
var data = event.target.result
console.log('reader onload for ' + fileName)
socket.emit('sendPiece', data, fileName, fileSize, entryID)
}
socket.on('morePlease', function (place, entryID, percent){
progressUpdate(percent)
var chunkSize = 262144
var startPlace = place * chunkSize // The newBlock's Starting Position
var newBlock = file.slice(startPlace, startPlace + Math.min(chunkSize, (fileSize-startPlace)))
reader.readAsBinaryString(newBlock) // triggers reader onload
})
function progressUpdate(percent){
console.log('current percent is: ' + percent + '%')
$('.sendfile .progress').val(percent).text(percent + '%')
}
socket.on('sendSuccessful', function(entryID){
console.log('sendSuccessful triggered for ' + entryID + '. File should be in temp folder.')
$('.status .sendfile').addClass('hidden')
$('.status .savetext').removeClass('hidden')
$('.status .saved').removeClass('hidden')
$('.sendfile .progress').val(0).text('0%')
})
} else {
// file size is too big
}
}) // close input onchange event
服务器.js
// start file upload
var chunkSize = 262144
socket.on('startSend', function(fileName, fileSize, entryID) {
var files = {}
console.log('startSend hit for ' + fileName)
files[fileName] = { // create new entry in files {}
fileSize : fileSize,
data : '',
downloaded : 0
}
var fileWriting = files[fileName]
var tempPath = 'temp/' + entryID + '-' + fileName
var place = 0 // stores where in the file we are up to
console.log('place: in startSend, the place for ' + fileName + ' is ' + place) //
try{
var stat = fs.statSync(tempPath)
if(stat.isFile())
{
fileWriting['downloaded'] = stat.size
place = stat.size / chunkSize; // we're passing data in 1/4 mb increments
console.log('downloaded: ' + stat.size)
}
}
catch(er){} // it's a new file
fs.open(tempPath, "a", 0755, function(err, fd){
if(err)
{
console.log(err)
}
else // requesting
{
fileWriting['handler'] = fd //We store the file handler so we can write to it later
var percent = 0
socket.emit('morePlease', place, entryID, percent) // requesting more file pieces
}
})
// processing the file pieces from client
socket.on('sendPiece', function(data, fileName, fileSize, entryID) {
console.log('sendPiece hit for ' + entryID + ' ' + fileName)
fileWriting['downloaded'] += data.length
fileWriting['data'] += data
if(fileWriting['downloaded'] == fileWriting['fileSize']) { // If File is Fully Uploaded
fs.write(fileWriting['handler'], fileWriting['data'], null, 'Binary', function(err, Writen){
console.log('file ' + entryID + 'has been written to temp folder: ' + fileName)
socket.emit('sendSuccessful', entryID)
})
}
else if(fileWriting['data'].length > 10485760){ //If the Data Buffer reaches 10MB
fs.write(fileWriting['handler'], fileWriting['data'], null, 'Binary', function(err, Writen){
fileWriting['data'] = ""; //Reset The Buffer
var place = fileWriting['downloaded'] / chunkSize
var percent = (fileWriting['downloaded'] / fileWriting['fileSize']) * 100
socket.emit('MorePlease', place, entryID, percent) // requesting more file pieces
})
}
else { // need more file pieces
var place = fileWriting['downloaded'] / chunkSize
console.log('MorePlease: ' + fileName + ' pieces needed at place ' + place + ' and percent ' + percent)
var percent = (fileWriting['downloaded'] / fileWriting['fileSize']) * 100
socket.emit('morePlease', place, entryID, percent) // requesting more file pieces
}
})
}) // close startSend
服务器日志:这是基于console.logs的节点日志分散在各处:
上传第一个文件没问题:
startSend hit for file1.jpeg
place: in startSend, the place for file1.jpeg is 0
sendPiece hit for 52a530f8649b5db8b2000001 file1.jpeg
file 52a530f8649b5db8b2000001has been written to temp folder: file1.jpeg
对于后续文件:
startSend hit for file2.JPG
place: in startSend, the place for file2.JPG is 0
sendPiece hit for 52a530f8649b5db8b2000001 file1.jpeg
MorePlease: file1.jpeg pieces needed at place 1.9332275390625 and percent undefined
sendPiece hit for 52a530f8649b5db8b2000001 file1.jpeg
MorePlease: file1.jpeg pieces needed at place 0.96661376953125 and percent undefined
sendPiece hit for 52a530f8649b5db8b2000001 file2.JPG
MorePlease: file2.JPG pieces needed at place 2.6120567321777344 and percent undefined
...无限循环。
webinspector 消息:
reader onload for file1.jpeg (client.js, line 260)
reader onload for file2.JPG (client.js, line 260)
current percent is: 270.227552566774% (client.js, line 273, x2)
current percent is: 242.3942545981759% (client.js, line 273)
InvalidStateError: DOM Exception 11: An attempt was made to use an object that is not, or is no longer, usable.
...无限循环
我已经为此绞尽脑汁好几个小时了,试图自己单步调试代码。我不是专业的开发人员,因此非常感谢任何帮助!
【问题讨论】:
标签: javascript jquery html node.js filereader