0

I am having issues uploading multiple files through chunking using javascript. With one file, it seems to work fine, but if there is more than 1 file, program execution stops and does not continue with the next file upload.

I know it's most likely an issue with async/await. Please let me know what I am doing wrong. What I would like to happen is the following: user drops multiple files-> file1 is chunked and read -> once complete -> file2 is chunked and read -> etc.

Here is a screenshot of the current output: enter image description here

You can see that the first file is uploaded, but then instead of continuing with second file, program execution stops.

Here is the code: function to loop through all files:

/* loop through all files and upload to server */
async loopThroughFiles(){
        for (const file of this.#files) {
            this.#file = file;
            this.#file_size = file.size;
            this.#total_file_size = this.#total_file_size + file.size;
            this.#file_count++;
            this.#file_type = file.type;
            this.#filename = file.name;
            console.log("filename: " + this.#filename);

            try {
                const result = await this.uploadFile(0, file); // uses fetch to send file server side
                console.log("finished uploading " + file.name);
                overallUploadStatusDiv.insertAdjacentHTML('afterend', file.name + result + "<br/>");
            }catch(err){
                console.log(err);
            }
        }
}

Function to uploadFile():

uploadFile(start,file) {
    return new Promise((resolve, reject) => {
    this.#next_slice = start + this.#slice_size + 1;
    let filePart = file.slice(start, this.#next_slice, this.#file_type);
    let fileReader = new FileReader();

    let self = this; // save object reference to use inside nested function
    fileReader.readAsDataURL(filePart);

    fileReader.onLoad = function (e) {
        return console.log("here is your data: " + e.target.result);
    };

    /** pass files in chunks to server **/
    //return new Promise((resolve, reject) => {
    fetch('../processFileUploadTEST.php', {
        method: 'POST',
        body: filePart
    }).then(response => {
        if (!response.ok) {
            throw new Error(response.statusText);
        }
    }).then(data => {
        //console.log("php data: " + data);
        var size_done = start + self.#slice_size;
        var percent_done = Math.floor(((size_done) / self.#file_size) * 100) + 1;
        let total_percent_done = Math.floor(((size_done) / self.#total_file_size) * 100) + 1;
        //console.log(self.#filename + " VS " + file.name);

        if (self.#next_slice < self.#file_size) {
            uploadStatusDiv.innerHTML = `Uploading: ${percent_done}`;
            self.uploadFile(self.#next_slice, file);
        } else {
            resolve(console.log("file " + self.#filename + " has been uploaded!"))
            //itemSpan[0].style.color = "blue";
        }
        overallUploadStatusDiv.innerHTML = `Total upload progress:   ${total_percent_done} %`;
    }).catch(error => console.log(error));

    }) // end Promise
} // end uploadFile function

} // end class

Any help/pointers in the right direction would be appreciated!

EDIT: I modified the code to make make proper use of async/await. The code is now working more like it should, except that it is not iterating the next files. It gets stuck after the first file. It seems that the promise never gets returned from the uploadFile() function, causing the for loop to stay on the current 1st iteration.

Can anybody see what I am doing wrong? I am attaching the new picture of the output. Thanks.

console output after code edit: enter image description here

2
  • you need to wait for uploadFile in your recursive call. like await self.uploadFile(self.#next_slice); Commented Jul 9, 2021 at 5:10
  • 1
    Thanks! I am looking into it. your suggestion required further modification of fetch function... I ll report back once I ve tried a few things. Commented Jul 9, 2021 at 6:02

2 Answers 2

1

fetch don't do a good job at reporting upload/download progress, this is one thing xhr is still better at then fetch.

const xhr = new XMLHttpRequest()
xhr.upload.onprogress = console.log
xhr.onprogress = console.log
xhr.open('POST', 'https://httpbin.org/post')
xhr.send(new File(['abc'], 'sample.txt'))

Sign up to request clarification or add additional context in comments.

Comments

0

After tinkering with the code and doing further research, I have decided to go with Uppy...they pretty much have already implemented what I need.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.