Filereader и Socket.io Uploader: последующие загрузки включают предыдущие загрузки

0

Я пытаюсь реализовать загрузчик файлов в html5/js и узел, который загружает большие файлы в куски. Он отлично работает для одной загрузки. Но когда я пытаюсь загрузить снова на той же странице, он переходит в бесконечный цикл, где он похож на попытку повторной загрузки предыдущей загрузки и нового файла сразу.

Client.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 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

Server.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 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

server log: Здесь журнал узлов основан на 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.

... бесконечная петля


Я много часов ломал голову над этим, пытаясь самостоятельно выполнить код. Я не разработчик по профессии, поэтому любая помощь будет оценена очень высоко!

Теги:
filereader

1 ответ

0
Лучший ответ

Я никогда не использую Socket для загрузки файлов с помощью Node.js. В основном, http делает отличную работу. Это пример кода:

var http = require('http'),
    fs = require('fs');

var server = http.createServer();
server.listen(8080);
console.log('Start is started on port 8080');

server.on('request', function(req, res) {
    var file = fs.createWriteStream('sample.jpg');
    var fileSize = req.headers['content-length'];
    var uploadedSize = 0;

    req.on('data', function (chunk) {
        uploadedSize += chunk.length;
        var buffer = file.write(chunk);
        if(buffer == false)
            req.pause();
    });

    file.on('drain', function() {
        req.resume();
    });

    req.on('end', function() {
        res.write('File uploading is completed!!');
        res.end();
    });
});

Если вы хотите уведомить клиента о выполнении загрузки, вы можете добавить некоторую логику в событие data.

Кстати, я обнаружил, что кто-то уже задал один и тот же вопрос и получил ответ. Ответ разместил ссылку на учебник. Я проверил и подумал, что это решение, которое вы ищете. Проверьте возможности загрузки файлов Node.js: Загрузка больших видеофайлов с поддержкой прерывания !

  • 0
    Причина, по которой я пошел с сокетом, заключается в том, что я не хотел обновлять страницу при отправке формы на стороне клиента. Разве модель типа запроса узла server.on не работает только с новыми запросами HTML-страниц?
  • 0
    Пример, который я разместил, предназначен для серверной части. Даже если вы используете Socket или http для подключения, вам все равно нужна страница (или собственное приложение) на стороне клиента для отправки файла на сервер. Если вы хотите, чтобы ваш клиент получил уведомление, он должен реализовать событие (например, событие «sendSuccessful») для получения и обработки информации с сервера.
Показать ещё 3 комментария

Ещё вопросы

Сообщество Overcoder
Наверх
Меню