react / react/react-native

Creating new `Blob` from `Uint8Array` produces garbage data

Open
#41,079 15 comments 1 reaction 0 assignees View on GitHub

Nobody has claimed this yet.

Issue: Author Provided Repro Never gets stale Newer Patch Available
Dominant language
C++
Stars
127k
Forks
25.3k
Avg merge
1d 23h
Merged PRs (30d)
4

Description

Description

I'm trying to manually convert base64 data to a Blob and vice versa. To do this I create a Uint8Array from the base64 data (with atob - polyfilled with base-64).

For example for a very simple PNG the resulting blob is about 3-4x as large as expected and the data is unrecognizable.

const base64Uri = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=";

const base64ToBlob = (b64Data, contentType, sliceSize = 512) => {
  const byteCharacters = atob(b64Data);
  const byteArray = new Uint8Array(byteCharacters.length);

  for (let n = 0; n < byteCharacters.length; n++) {
    byteArray[n] = byteCharacters.charCodeAt(n);
  }

  return new Blob([byteArray], { type: contentType });
};
const blobToBase64Uri = (blob) => {
  return new Promise((resolve, reject) => {
    const reader = new FileReader();
    reader.onload = () => {
      resolve(reader.result);
    };

    reader.readAsDataURL(blob);
  });
};

const [_, type, base64] = base64Uri.match(/^data:(.*);base64,(.*)/) ?? [];

console.log(base64Uri)
// result: data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAAgAAAAIAQMAAAD+wSzIAAAABlBMVEX///+/v7+jQ3Y5AAAADklEQVQI12P4AIX8EAgALgAD/aNpbtEAAAAASUVORK5CYII=
blobToBase64Uri(base64ToBlob(base64, type)).then(console.log)
// result: data:image/png;base64,MTM3LDgwLDc4LDcxLDEzLDEwLDI2LDEwLDAsMCwwLDEzLDczLDcyLDY4LDgyLDAsMCwwLDgsMCwwLDAsOCwxLDMsMCwwLDAsMjU0LDE5Myw0NCwyMDAsMCwwLDAsNiw4MCw3Niw4NCw2OSwyNTUsMjU1LDI1NSwxOTEsMTkxLDE5MSwxNjMsNjcsMTE4LDU3LDAsMCwwLDE0LDczLDY4LDY1LDg0LDgsMjE1LDk5LDI0OCwwLDEzMywyNTIsMTYsOCwwLDQ2LDAsMywyNTMsMTYzLDEwNSwxMTAsMjA5LDAsMCwwLDAsNzMsNjksNzgsNjgsMTc0LDY2LDk2LDEzMA==

The same code works fine on the web and outputs the same result for both log statements.

React Native Version

0.72.6

Output of npx react-native info

System:
OS: macOS 14.0
CPU: (10) arm64 Apple M1 Pro
Memory: 551.34 MB / 32.00 GB
Shell:
version: "5.9"
path: /bin/zsh
Binaries:
Node:
version: 20.8.0
path: /opt/homebrew/bin/node
Yarn:
version: 1.22.19
path: /usr/local/bin/yarn
npm:
version: 10.2.0
path: /opt/homebrew/bin/npm
Watchman:
version: 2023.10.09.00
path: /opt/homebrew/bin/watchman
Managers:
CocoaPods:
version: 1.13.0
path: /opt/homebrew/bin/pod
SDKs:
iOS SDK:
Platforms:
- DriverKit 23.0
- iOS 17.0
- macOS 14.0
- tvOS 17.0
- watchOS 10.0
Android SDK: Not Found
IDEs:
Android Studio: 2021.2 AI-212.5712.43.2112.8609683
Xcode:
version: 15.0/15A240d
path: /usr/bin/xcodebuild
Languages:
Java:
version: 11.0.20.1
path: /usr/bin/javac
Ruby:
version: 2.6.10
path: /usr/bin/ruby
npmPackages:
"@react-native-community/cli": Not Found
react:
installed: 18.2.0
wanted: 18.2.0
react-native:
installed: 0.72.5
wanted: 0.72.5
react-native-macos: Not Found
npmGlobalPackages:
"react-native": Not Found
Android:
hermesEnabled: Not found
newArchEnabled: Not found
iOS:
hermesEnabled: Not found
newArchEnabled: Not found

Steps to reproduce
  1. Install base-64
  2. run the code given in the instructions somewhere in your app
Snack, screenshot, or link to a repository

https://snack.expo.dev/@stefan-5gpay/base64blobbug

On the web version both are the same:

image

On device (same for iOS and Android) data is different:

IMG_3631

Contributor guide

Open the contributing guide

First steps

  1. Read the whole issue, then the project's contributing guide.
  2. Comment on the issue to say you are picking it up — it saves two people doing the same work.
  3. Fork the repository and make your change on a branch.
  4. Open a pull request that references the issue number.

Research direction

Start with the provided Snack reproduction and run the base64-to-Blob example on web, iOS, and Android to compare the encoded results. Trace the React Native Blob and Uint8Array handling involved in the repro; done means the round trip preserves the original PNG data on devices as it does on the web.

Written by the indexing model from the issue text.

Assessment

Tech stack
javascript, react-native
Domain
mobile-dev
Issue type
Bug
Difficulty
4/5
Estimated time
3-5 days
Activity status
Stale
Clarity
Mostly clear
Newbie friendliness
35/100

Get new issues in your inbox

A short digest of beginner-friendly GitHub issues.