7

I load two blob files in JavaScript using the code below.

I want to compare them to see if they are precisely the same.

(blob1 === blob2) is returning false, even though the reported size of each blob is 574 bytes. What am I doing wrong?

  getHTTPAsBlob(url, callback) {
    let cacheBust = Math.random().toString()
    url = url + '?&cachebust=' + cacheBust
    let xhr = new XMLHttpRequest();
    xhr.open('GET', url, true);
    xhr.responseType = 'blob';
    xhr.onload = function (e) {
      if (xhr.status == 200) {
        // get binary data as a response
        let fileData = this.response;
        let contentType = xhr.getResponseHeader("content-type")
        var reader = new FileReader()
        reader.onload = (e) => {
          console.log(reader.result)
          console.log(fileData)
          callback(null, {
              Body: reader.result,
              Blob: fileData,
              ContentType: contentType,
              Etag: null,
              LastModified: null,
            })
        }
        reader.readAsText(fileData)
        } else {
        callback(xhr)
      }
      }
      xhr.send();
    }
3
  • 2
    I think you have to read the "blob" if you want to compare its contents (using FileReader). Wouldn't it be easier to set responseType to "arraybuffer", especiallly if they are so small? Commented Aug 14, 2016 at 9:46
  • If you look at my code you'll see it uses filereader to get the text out of the blob but that is beside the point, reading should not be needed for comparing two blobs. Commented Aug 14, 2016 at 12:20
  • @DukeDugal: Why would reading not be needed to compare two blobs? How else do you want to compare them, if not by their contents? Commented Aug 14, 2016 at 23:22

6 Answers 6

2

You must use a FileReader to compare them

The documentation for FileReader is on MDN. Take a look at methods to choose what's best for your data.

A useless way of comparing two blobs is looking at their size. Although two blobs of the same size will return true no matter their content.

Example

new Blob([Math.random()]).size == new Blob([Math.random()]).size // true.

Full code:

const input = document.querySelector('input');
input.addEventListener('change', async (e) => {

  e.preventDefault();

  const { files } = e.target; // <= Contains the FileList

  if ( files.length < 2 || files.length > 2 ){
    return console.log("Please select 2 files!");
  }

  // A) Convert files to ArrayBuffer:
  const arrayBufferFileA = await e.target.files[0].arrayBuffer();
  const arrayBufferFileB = await e.target.files[1].arrayBuffer();

  // Stop if the files are not the same size:
  if ( arrayBufferFileA.byteLength !== arrayBufferFileB.byteLength ){
    return console.log("Files are not the same size!");
  }

  // B) Convert ArrayBuffer to Uint8Array for byte-size comparison:
  const uint8ArrayA = new Uint8Array(arrayBufferFileA);
  const uint8ArrayB = new Uint8Array(arrayBufferFileB);
  
  let filesAreTheSame = true;

  for (let i = 0, len = uint8ArrayA.length; i < len; i++) {
    if ( uint8ArrayA[i] !== uint8ArrayB[i] ){
      filesAreTheSame = false;
      break;
    }
  }

  if ( filesAreTheSame ){
    console.log("Files are the same!");
  } else {
    console.log("Files are not the same!");
  }

})
<input type="file" multiple>

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

Comments

1

I think "blob compare" plug-in will be help you. It can compare blob size,type and so on. https://www.npmjs.com/package/blob-compare

but I don't know if this plug-in is the perfect way.

1 Comment

In 2023, i'm using blob-compare. See my answer for another similar question here: stackoverflow.com/a/77342813/6122411
0

Unfortunately, this is a case of comparing two completely independent pointers that reference comparable content. To see how this might work for simpler content, try the following in the javascript console:

new Number(5) == new Number(5)

Returns false. Frustrating that 5 as an object does not equal an object whose value is 5. But at least this puts Blob into context.

I'm running into this same problem, and agree with the previous suggestion that FileReader is the only option.

Comments

0

The question was asked in context of JavaScript in the browser, but in case anyone wants to compare blobs in Node.js:

const areBlobsEqual = async (blob1, blob2) => {
  return !Buffer.from(await blob1.arrayBuffer()).compare(
    Buffer.from(await blob2.arrayBuffer())
  );
};

Comments

0

See this answer to a similar question: https://stackoverflow.com/a/77342813/6122411

In short, it is to Convert the File/Blob to ArrayBuffer using FileReader. Then perform byte-to-byte check on the buffer. A library is recommended in that above answer.

Comments

0

Convert Blobs to Base64 and then compare the strings

This solution:

  • works in the browser
  • is simple and requires no library
  • might not have the best performance

First, we create a function that converts blobs (including files) into base64 strings:

export function blobToBase64(blob: Blob) {
    return new Promise<string>((resolve, reject) => {
        const reader = new FileReader();
        reader.onloadend = () => resolve(reader.result as string);
        reader.onerror = (error) => reject(error);
        reader.readAsDataURL(blob);
    });
}

Then we use that function to compare the base64 strings of two blobs:

export async function compareBlobs(a: Blob, b: Blob): Promise<boolean> {
    return (await blobToBase64(a)) === (await blobToBase64(b));
}

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.