브라우저 클라이언트와 Node.js 서비스는 동일한 바이트에 대해 동일한 Base64을 생성해야 합니다. 이를 수행하기 위해 동일한 API을 사용할 필요는 없습니다. 중요한 합의는 텍스트의 바이트 표현, 알파벳, 패딩 처리 및 유효하지 않은 입력입니다.
브라우저: UTF-8 단계를 명시적으로 만듭니다.
기존 브라우저 기능은 바이트 문자열에서 작동합니다. 다음을 사용하여 유니코드 텍스트 변환 TextEncoder, 그런 다음 해당 바이트를 인코딩합니다. 반환 경로에서 바이트 배열을 재구성하고 UTF-8을 명시적으로 디코딩합니다. 이 예에서는 루프를 사용하여 큰 배열을 함수 인수로 확장하는 것을 방지합니다. 하지만 프로덕션 파일 인코더는 여전히 제한된 청크 또는 적절한 바이트 API을 사용해야 합니다.
const text = '中文😊';
const bytes = new TextEncoder().encode(text);
let binary = '';
for (const byte of bytes) binary += String.fromCharCode(byte);
const encoded = btoa(binary);
console.log(encoded); // 5Lit5paH8J+Yig==
const decodedBytes = Uint8Array.from(atob(encoded), c => c.charCodeAt(0));
const decoded = new TextDecoder('utf-8', { fatal: true }).decode(decodedBytes);
console.log(decoded); // 中文😊
Node.js: 바이트 경계에서 Buffer을 유지합니다.
Buffer.from(text, 'utf8') 텍스트 인코딩을 표시합니다. 전화 toString('base64') 그런 다음 해당 바이트를 나타냅니다. Buffer으로 디코딩하면 이진 데이터가 보존됩니다. 즉시 UTF-8 문자열로 변환하는 것은 페이로드가 텍스트로 알려진 경우에만 적합합니다.
import { Buffer } from 'node:buffer';
const encoded = Buffer.from('中文😊', 'utf8').toString('base64');
console.log(encoded); // 5Lit5paH8J+Yig==
const bytes = Buffer.from(encoded, 'base64');
console.log(new TextDecoder('utf-8', { fatal: true }).decode(bytes)); // 中文😊
예제의 치명적인 TextDecoder은 의도적인 것입니다. 일반 Buffer UTF-8 문자열 변환은 유효하지 않은 입력에 대해 대체 문자를 삽입할 수 있습니다. 성공적인 텍스트 표시는 원래 바이트가 충실하게 표시될 수 없다는 사실을 숨깁니다.
별도 검증 동의
노드의 Base64 디코더는 더 엄격한 애플리케이션에서는 거부할 수 있는 일부 입력 형식을 허용합니다. 성공적인 Buffer 변환을 프로토콜의 정식 표현이 제공되었다는 증거로 사용하지 마세요. 서명, 캐시 키 또는 상호 운용 가능한 직렬화에 대한 정확한 구문이 중요한 경우 디코딩하기 전에 확인하십시오.
공유 회귀 테스트의 경우 ASCII, 중국어, 이모티콘, 0바이트, FF 바이트 및 3바이트 경계 주변의 모든 길이를 포함합니다. 런타임 전반에 걸쳐 바이트를 비교합니다. 또한 대체 문자를 실제로 포함하는 고정 장치를 사용하여 URL-안전한 출력을 테스트하세요. 출력이 문자로만 이루어진 입력은 변형 옵션이 작동함을 증명할 수 없습니다.
Node에서 파일을 읽을 때 읽은 파일에 텍스트 인코딩을 적용하는 대신 반환된 Buffer을 유지하세요. 브라우저에서 다음을 사용하십시오. File.arrayBuffer(). 이러한 작은 경계 선택은 대부분의 우발적인 손상을 방지합니다. 참조 Node.js Buffer 노드 동작 및 MDN: btoa() 브라우저 바이트 문자열 계약의 경우.