skip to Main Content

I’ve tried a lot of things before, but I can’t seem to process how to do it correctly.

Here’s my problem : I want my users to upload an Excel File and then fetch the lines to upload it on my database. I’ve made the JavaScript and PHP scripts and it works pretty well, but while it’s fetching the lines, I want to show the user a loader saying "Line current_line of total_lines". I’ve tried the following script :

But it does not seem to work and I don’t understand why. In my PHP, "finances/import" upload the lines with a for loop and iterate a session variable then read in "finances/import_progress" but the loader is updated when the import is over and I don’t understand why.

I’ve tried to change the fetch in CheckImportProgress with XHR and the onprogress method but it didn’t change anything.

fetch(baseurl + 'finances/import', {
    method: 'POST',
    ContentType: 'multipart/form-data; boundary=—-WebKitFormBoundaryfgtsKTYLsT7PNUVD',
    body: form
  })
  .then(response => response.json())
  .then(json => {
    if (json.success) {
      //On récupère le nombre de lignes du fichier Excel uploadé
      nbrlignes = json.nbrlines
      document.querySelector('.infoslignes').style.display = 'block'
      document.querySelector('.ligneimport').innerHTML = 0
      document.querySelector('.lignetotal').innerHTML = nbrlignes
      fetch(baseurl + 'finances/import_excel', {
        method: 'POST',
        headers: {
          'Accept': 'application/json',
          'Content-Type': 'application/json'
        },
        body: JSON.stringify({
          page: document.querySelector('input[name="page"]').value,
          file: json.file
        })
      })
      setInterval(checkImportProgress, 500, nbrlignes)
    } else {
      document.querySelector('.error-import').style.display = 'block'
      document.querySelector('.error-import').innerHTML = json.message
      document.querySelector('.import-text').style.display = 'block'
      document.querySelector('.import-progress').style.display = 'none'
    }
  })

function checkImportProgress(nbrlignes) {
  fetch(baseurl + 'finances/import_progress/' + nbrlignes)
    .then(response => response.json())
    .then(json => {
      document.querySelector('.import-progress-bar').style.width = ((json.row / nbrlignes) * 100) + '%'
      document.querySelector('.import-progress-bar').innerHTML = Math.round(((json.row / nbrlignes) * 100)) + '%'
      document.querySelector('.ligneimport').innerHTML = json.row
      if (nbrlignes === json.row)
        clearInterval()
    })
}

2

Answers


  1. How about, try to read the file in js, then store it in variable. After that, you can use a batch request for uploading your data. In that way, you can display to the user what data is currently uploading.

    Login or Signup to reply.
  2. One fundamental issue is the idea of retrieving the amount of lines from the backend whilst uploading it. The backend cannot access this data until the upload is complete.

    You’ll want to use a package such as this one to make it much easier for you to retrieve the line count on the frontend:

    const getExcelFileRowCount = async file => {
        const workbook = new Excel.Workbook();
        const worksheet = await workbook.xlsx.read(file.stream());
        
        // Doesn't technically need to be column 1, but that will always exist, so it's fine.
        const rows = worksheet.getColumn(1);
        return rows["_worksheet"]["_rows"].length;
    };
    

    Secondly, it would be very difficult to know which line is currently being processed, since technically the upload isn’t processing individual lines, but the bytes themselves.

    So, to give the user a faux approximation of what "line" is currently being processed, you can use the uploadProgress value from a library such as axios:

    const rowCount = await getExcelFileRowCount(fileInput);
    
    const handleProgressUpdate = progress => {
        console.log(Math.floor(rowCount * progress));
    };
    
    const formData = new FormData();
    formData.append("file", fileInput);
    
    axios.post("finances/import", formData, {
        onUploadProgress: handleProgressUpdate
    });
    

    Hope this helps mate.

    Login or Signup to reply.
Please signup or login to give your own answer.
Back To Top
Search