1

I am trying to send a large file to a server, so I am using the chunking technique in order to do it in a robust way.

    private readonly sendChunk = (file: File, progressModel: ProgressResponseModel): void => {
        const offset = progressModel.Offset;
        if (offset > file.size)
            throw new Error("Offset cannot be greater than the file size");

        const expectedSize = progressModel.ExpectedChunkSize;

        const blobChunk = file.slice(offset, expectedSize);

        const xhr = new XMLHttpRequest();
        xhr.onload = (ev: Event): void => {
             if (xhr.readyState === XMLHttpRequest.DONE && xhr.status === 200) {
                    const progress = this.progressFromText(xhr.responseText);

                    if (progress.Offset >= 0) {
                        this.sendChunk(file, progress);
                    }

                    console.log(`${progress.Progress} %`);
                }
            }

        xhr.open("POST", this._uploadChunkUrl, true);
        xhr.send(blobChunk);
    }

The server sends back where to start the new chunk from and how big it should be. The above function is executed in a recursive manner as you can see.

However, if the file requires more than 1 chunk to be sent, the second time I call const blobChunk = file.slice(offset, expectedSize); I get an empty chunk (length 0).

I can guarantee that the file arg is always valid (when console.loged).

I've seen this question, but I am sure my file is not removed or renamed. I've also seen this issue. I get the same behavior for both Chrome and Firefox (latest versions), also Edge.

Thanks!

UPDATE Okay, so I did a dummy method in order to isolate this issue:

    readonly chunkIt = (file: Blob): void => {
        var offset = 0;
        var length = 512 * 1024;

        while (offset >= 0) {
            const blobChunk = file.slice(offset, length);
            console.log(blobChunk);

            offset += length;
            if (offset > file.size) offset = -1;
        }
    }

And using it:

   $("input[name='fileUpload']").on("change", (e) => {
        const files = e.target.files;
        if (typeof files === "undefined" || files === null || files.length === 0)
            e.preventDefault();

        const file = files[0];

        this._client.chunkIt(file);
    });

Logs a correct Blob only the first time, the following are all empty.

SOLVED

From this issue - Splitting a File into Chunks with Javascript it turned out that I've forgot to offset my end index.

Martin Shishkov
  • 2,709
  • 5
  • 27
  • 44

1 Answers1

0

You need to use splice() instead of slice()

Replace

const blobChunk = file.slice(offset, expectedSize);

with

const blobChunk = file.splice(offset, expectedSize);
Ankit Agarwal
  • 30,378
  • 5
  • 37
  • 62