├── .gitignore ├── .npmignore ├── tsup.config.ts ├── tsconfig.json ├── package.json ├── README.MD └── src └── index.ts /.gitignore: -------------------------------------------------------------------------------- 1 | 2 | # Build files 3 | /dist 4 | 5 | # Node Modules 6 | /node_modules 7 | -------------------------------------------------------------------------------- /.npmignore: -------------------------------------------------------------------------------- 1 | 2 | # Build files 3 | /src 4 | 5 | # Node Modules 6 | /node_modules 7 | 8 | # TS stuff 9 | tsconfig.json 10 | tsup.config.ts 11 | -------------------------------------------------------------------------------- /tsup.config.ts: -------------------------------------------------------------------------------- 1 | import { defineConfig } from 'tsup'; 2 | 3 | export default defineConfig({ 4 | format: ['cjs', 'esm'], 5 | entry: ['./src/index.ts'], 6 | dts: true, 7 | shims: true, 8 | skipNodeModulesBundle: true, 9 | clean: true, 10 | }); -------------------------------------------------------------------------------- /tsconfig.json: -------------------------------------------------------------------------------- 1 | { 2 | "compilerOptions": { 3 | "strict": true, 4 | "noImplicitAny": true, 5 | "esModuleInterop": true, 6 | "strictNullChecks": true, 7 | "target": "ES2022", 8 | "moduleResolution": "Node10", 9 | "module": "CommonJS", 10 | "declaration": true, 11 | "isolatedModules": true, 12 | "noEmit": true, 13 | "outDir": "dist" 14 | }, 15 | "include": ["src"], 16 | "exclude": ["node_modules"] 17 | } -------------------------------------------------------------------------------- /package.json: -------------------------------------------------------------------------------- 1 | { 2 | "name": "use-blob-to-file", 3 | "description": "A React hook for converting Data URLs / Blob files into File objects with a preview URL for easy viewing and uploading.", 4 | "version": "0.0.4", 5 | "main": "./dist/index.js", 6 | "module": "./dist/index.mjs", 7 | "types": "./dist/index.d.ts", 8 | "homepage": "https://github.com/MohammedIbrahim8887/use-blob-to-file", 9 | "repository": { 10 | "url": "https://github.com/MohammedIbrahim8887/use-blob-to-file" 11 | }, 12 | "scripts": { 13 | "build": "tsup" 14 | }, 15 | "keywords": [ 16 | "react", 17 | "hook", 18 | "blob", 19 | "file", 20 | "typescript", 21 | "blob to file", 22 | "data url to file" 23 | ], 24 | "author": "doughnut4641", 25 | "license": "MIT", 26 | "devDependencies": { 27 | "@types/react": "^18.3.3", 28 | "tsup": "^8.2.4", 29 | "typescript": "^5.5.4", 30 | "react": "^18.3.1" 31 | }, 32 | "dependencies": {} 33 | } -------------------------------------------------------------------------------- /README.MD: -------------------------------------------------------------------------------- 1 | # `useBlobToFile` 2 | 3 | A React hook for effortlessly converting Data URLs / Blob files into File objects, complete with a preview URL for easy viewing and uploading. 4 | 5 | ## 📦 Installation 6 | 7 | You can install the package using npm, Yarn, pnpm, or Bun: 8 | 9 | ### Using npm 10 | 11 | ```bash 12 | npm install use-blob-to-file 13 | ``` 14 | 15 | ### Using Yarn 16 | 17 | ```bash 18 | yarn add use-blob-to-file 19 | ``` 20 | 21 | ### Using pnpm 22 | 23 | ```bash 24 | pnpm add use-blob-to-file 25 | ``` 26 | 27 | ### Using Bun 28 | 29 | ```bash 30 | bun add use-blob-to-file 31 | ``` 32 | 33 | ## 🔧 Usage 34 | 35 | Import and use the `useBlobToFile` hook in your React components: 36 | 37 | ```jsx 38 | import React from 'react'; 39 | import useBlobToFile from 'use-blob-to-file'; 40 | 41 | const MyComponent = () => { 42 | const dataUrl = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA...'; // Replace with your Data URL 43 | const filename = 'my-image.png'; 44 | 45 | const { file, previewUrl } = useBlobToFile({ dataUrl, filename }); 46 | 47 | return ( 48 |
49 | Preview 50 | Download File 51 |
52 | ); 53 | }; 54 | 55 | export default MyComponent; 56 | ``` 57 | 58 | ## 🌟 Features 59 | 60 | - **Convert Data URLs to File Objects**: Easily convert base64-encoded Data URLs into File objects. 61 | - **Preview URL**: Generate a preview URL to view the file before uploading. 62 | - **TypeScript Support**: Fully typed with TypeScript for a better development experience. 63 | 64 | ## 🛠️ React Hook 65 | 66 | ### `useBlobToFile` 67 | 68 | ```typescript 69 | const useBlobToFile = (args: DataUrlToFileProps) => { 70 | // Returns an object with `file` and `previewUrl` 71 | } 72 | ``` 73 | 74 | #### Parameters 75 | 76 | - **`args`** (`DataUrlToFileProps`): The parameters for conversion. 77 | - `dataUrl` (string): The Data URL to convert. 78 | - `filename` (string): The name of the file to be created. 79 | 80 | #### Returns 81 | 82 | - **`file`** (`File`): The created File object. 83 | - **`previewUrl`** (`string`): A URL for previewing the file. 84 | 85 | ## 📝 License 86 | 87 | This package is licensed under the MIT License. See the [LICENSE](LICENSE) file for details. -------------------------------------------------------------------------------- /src/index.ts: -------------------------------------------------------------------------------- 1 | import { useEffect, useState } from 'react'; 2 | 3 | /** 4 | * Converts a data URL to a File object and generates a preview URL. 5 | * Handles both Base64-encoded and non-Base64 data URLs. 6 | * Automatically cleans up object URLs to prevent memory leaks. 7 | */ 8 | const useBlobToFile = (dataUrl: string, filename: string) => { 9 | const [file, setFile] = useState(null); 10 | const [previewUrl, setPreviewUrl] = useState(null); 11 | 12 | useEffect(() => { 13 | let objectUrl: string | null = null; 14 | 15 | /** 16 | * Process the data URL and convert it to a File object with a preview URL. 17 | * Handles Base64 and non-Base64 data URLs. 18 | */ 19 | const processDataUrl = () => { 20 | const isBase64 = dataUrl.includes("base64"); 21 | let data: string | Uint8Array = ''; 22 | let contentType: string; 23 | const parts = dataUrl.split(";"); 24 | 25 | if (isBase64) { 26 | /** 27 | * Extract the content type and Base64-encoded content from the data URL 28 | */ 29 | contentType = parts[0].split(":")[1]; 30 | data = parts[1].split(",")[1]; 31 | 32 | /** 33 | * Convert the Base64-encoded content to binary data 34 | */ 35 | const binaryData = atob(data); 36 | const arrayBuffer = new ArrayBuffer(binaryData.length); 37 | const uint8Array = new Uint8Array(arrayBuffer); 38 | for (let i = 0; i < binaryData.length; i++) { 39 | /** 40 | * Converts each character to byte value 41 | */ 42 | uint8Array[i] = binaryData.charCodeAt(i); 43 | } 44 | data = uint8Array; 45 | } else { 46 | /** 47 | * This handles URL-encoded binary data 48 | */ 49 | contentType = parts[0].split(":")[1]; 50 | data = decodeURIComponent(parts[1].split(",")[1]); 51 | } 52 | 53 | /** 54 | * Create a Blob from the binary data or URL-decoded data 55 | */ 56 | const blob = new Blob([data], { type: contentType }); 57 | 58 | /** 59 | * Create a File object with the specified filename 60 | */ 61 | const fileObj = new File([blob], filename, { type: contentType }); 62 | 63 | /** 64 | * Generate a preview URL for the File object 65 | */ 66 | objectUrl = URL.createObjectURL(fileObj); 67 | 68 | setFile(fileObj); 69 | setPreviewUrl(objectUrl); 70 | }; 71 | 72 | processDataUrl(); 73 | 74 | /** 75 | * Cleanup function to revoke the object URL and free memory 76 | */ 77 | return () => { 78 | if (objectUrl) { 79 | URL.revokeObjectURL(objectUrl); 80 | } 81 | }; 82 | }, [dataUrl, filename]); 83 | 84 | return { file, previewUrl }; 85 | }; 86 | 87 | export default useBlobToFile; 88 | --------------------------------------------------------------------------------