{"_id":"@aiyeola/react-firebase-file-uploader","name":"@aiyeola/react-firebase-file-uploader","dist-tags":{"latest":"1.0.0"},"versions":{"1.0.0":{"name":"@aiyeola/react-firebase-file-uploader","version":"1.0.0","description":"A file uploader for react that uploads files to your firebase storage","main":"lib/index.js","scripts":{"build":"babel src --out-dir lib","prepublish":"npm run build"},"babel":{"presets":["@babel/preset-react","@babel/preset-env"]},"repository":{"type":"git","url":"git+https://github.com/aiyeola/react-firebase-file-uploader.git"},"keywords":["react","firebase","storage"],"author":{"name":"Frank van der Hoek","email":"frank.vanderhoek@gmail.com"},"license":"MIT","bugs":{"url":"https://github.com/aiyeola/react-firebase-file-uploader/issues"},"homepage":"https://github.com/aiyeola/react-firebase-file-uploader#readme","peerDependencies":{"firebase":"^3.5.2 || ^4.0.0 || ^5.0.0 || ^6.0.0 || ^7.0.0 || ^8.0.0 || ^9.0.0 || ^10.0.0","react":"^15.3.2 || ^16.0.0 || ^17.0.0 || ^18.0.0"},"devDependencies":{"@babel/cli":"^7.23.0","@babel/core":"^7.23.0","@babel/preset-env":"^7.23.0","@babel/preset-react":"^7.23.0","prettier":"^3.0.3"},"dependencies":{"uuid":"^9.0.1"},"_id":"@aiyeola/react-firebase-file-uploader@1.0.0","gitHead":"c3dc188baa99ca5af79b5fba77870a8469279c11","_nodeVersion":"22.11.0","_npmVersion":"10.9.0","dist":{"integrity":"sha512-X0VQwQdr4kYjsApqiGg7L5w8pu7NLitpLjN30Ov6qsaarvH0XYiFKyMO3zsWnNkDJtkE5D7YTJ9VpId+aqgvSg==","shasum":"9d74e50ddbec25f81d2db28496bbf8fd5a69c9bd","tarball":"https://registry.npmjs.org/@aiyeola/react-firebase-file-uploader/-/react-firebase-file-uploader-1.0.0.tgz","fileCount":14,"unpackedSize":54233,"signatures":[{"keyid":"SHA256:DhQ8wR5APBvFHLF/+Tc+AYvPOdTpcIDqOhxsBHRwC7U","sig":"MEUCICQ907y4+D4wpU++qE5sf32pCBrXrb9w9c9tdtqG/OI9AiEA1Ns7FE7DqGt6+SW2GUuN5Ql3c+c1b4MUn+9o3zvn4tM="}]},"_npmUser":{"name":"aiyeola","email":"aiyeolavictor@gmail.com"},"directories":{},"maintainers":[{"name":"aiyeola","email":"aiyeolavictor@gmail.com"}],"_npmOperationalInternal":{"host":"s3://npm-registry-packages-npm-production","tmp":"tmp/react-firebase-file-uploader_1.0.0_1742334640338_0.7428197521582367"},"_hasShrinkwrap":false}},"time":{"created":"2025-03-18T21:50:40.258Z","1.0.0":"2025-03-18T21:50:40.531Z","modified":"2025-03-18T21:50:40.765Z"},"maintainers":[{"name":"aiyeola","email":"aiyeolavictor@gmail.com"}],"description":"A file uploader for react that uploads files to your firebase storage","homepage":"https://github.com/aiyeola/react-firebase-file-uploader#readme","keywords":["react","firebase","storage"],"repository":{"type":"git","url":"git+https://github.com/aiyeola/react-firebase-file-uploader.git"},"author":{"name":"Frank van der Hoek","email":"frank.vanderhoek@gmail.com"},"bugs":{"url":"https://github.com/aiyeola/react-firebase-file-uploader/issues"},"license":"MIT","readme":"# react-firebase-file-uploader\n\nA file uploader for react that uploads images, videos and other files to your firebase storage.\n\n## Props\n\n- `storageRef` (required) - A reference to the firebase storage folder, where the file should be saved.\n- `onUploadStart` - A callback function that is called with the selected file as its first argument and the upload task as its second argument.\n- `onProgress` - A callback function that is called with the progress (between 0 and 100) as its first argument and the upload task as its second argument.\n- `onUploadSuccess` - A callback function that is called with the filename of the uploaded file as its first argument and the upload task as its second argument.\n- `onUploadError` - A callback function that is called with a [Firebase error](https://firebase.google.com/docs/storage/web/handle-errors) in case of an error during the upload process.\n- `filename` - The name you would like to give to the file. This can either be a function or a string. If a function is provided, it will be called with the selected file as its first and only argument. If no value is provided, it will use the filename of the file itself or a random generated name if `randomizeFilename` is set to true.\n- `metadata` - An object with the metadata that should be added to the file. You can use this for example to configure caching for your file with `metadata={{cacheControl: 'max-age=3600'}}`.\n- `randomizeFilename` - If true, generates a random filename for your file.\n- `hidden` - If true the rendered html input element will be hidden. This is useful if you want to [render a custom button](#rendering-a-custom-button).\n- `as` - The component you provide in this prop will be rendered instead of the standard html `input`.\n- `maxHeight` - The maximum height of in case an image is provided, please see below for more explanation.\n- `maxWidth` - The maximum width in case a image is provided.\n  The image will be scaled down, such that the image is contained in the maxWidth/maxHeight region.\n  The resulting image will be centered and the parts that stick out will be cropped off.\n- Default props of a html `input` such as `accept`, `disabled`, `form`, `formNoValidate`, `name`, `readOnly`, `required`, `value`, `multiple`.\n\n## Prerequisites\n\nMake sure you have initialized firebase somewhere in your app using:\n\n```jsx\nimport firebase from \"firebase\";\n\nconst config = {\n  apiKey: \"<API_KEY>\",\n  authDomain: \"<PROJECT_ID>.firebaseapp.com\",\n  databaseURL: \"https://<DATABASE_NAME>.firebaseio.com\",\n  storageBucket: \"<BUCKET>.appspot.com\"\n};\nfirebase.initializeApp(config);\n```\n\n## Example\n\n```jsx\nimport React, { Component } from \"react\";\nimport firebase from \"firebase\";\nimport FileUploader from \"react-firebase-file-uploader\";\n\nclass ProfilePage extends Component {\n  state = {\n    username: \"\",\n    avatar: \"\",\n    isUploading: false,\n    progress: 0,\n    avatarURL: \"\"\n  };\n\n  handleChangeUsername = event =>\n    this.setState({ username: event.target.value });\n  handleUploadStart = () => this.setState({ isUploading: true, progress: 0 });\n  handleProgress = progress => this.setState({ progress });\n  handleUploadError = error => {\n    this.setState({ isUploading: false });\n    console.error(error);\n  };\n  handleUploadSuccess = filename => {\n    this.setState({ avatar: filename, progress: 100, isUploading: false });\n    firebase\n      .storage()\n      .ref(\"images\")\n      .child(filename)\n      .getDownloadURL()\n      .then(url => this.setState({ avatarURL: url }));\n  };\n\n  render() {\n    return (\n      <div>\n        <form>\n          <label>Username:</label>\n          <input\n            type=\"text\"\n            value={this.state.username}\n            name=\"username\"\n            onChange={this.handleChangeUsername}\n          />\n          <label>Avatar:</label>\n          {this.state.isUploading && <p>Progress: {this.state.progress}</p>}\n          {this.state.avatarURL && <img src={this.state.avatarURL} />}\n          <FileUploader\n            accept=\"image/*\"\n            name=\"avatar\"\n            randomizeFilename\n            storageRef={firebase.storage().ref(\"images\")}\n            onUploadStart={this.handleUploadStart}\n            onUploadError={this.handleUploadError}\n            onUploadSuccess={this.handleUploadSuccess}\n            onProgress={this.handleProgress}\n          />\n        </form>\n      </div>\n    );\n  }\n}\n\nexport default ProfilePage;\n```\n\n### Rendering a custom button\n\nMost of the times the default html input element doesn't look very nice. There are two ways in which you can render a custom button:\n\n#### Wrapping the input in a label\n\nYou can render a custom button by wrapping the upload component in a `label` as follows:\n\n```jsx\n...\n  <label style={{backgroundColor: 'steelblue', color: 'white', padding: 10, borderRadius: 4, cursor: 'pointer'}}>\n    Select your awesome avatar\n    <FileUploader\n      hidden\n      accept=\"image/*\"\n      storageRef={firebase.storage().ref('images')}\n      onUploadStart={this.handleUploadStart}\n      onUploadError={this.handleUploadError}\n      onUploadSuccess={this.handleUploadSuccess}\n      onProgress={this.handleProgress}\n    />\n  </label>\n...\n```\n\nPlease note that you will need to provide the `hidden` prop to hide the default html input element.\n\nThe above code will render this:\n\n![Custom Button](assets/custom-button.png)\n\n#### Using the `CustomUploadButton` component\n\nThere is a littel helper component that you can find in `'react-firebase-file-uploader/lib/CustomUploadButton'`. This component will wrap the input in a label for you and automatically adds the `pointer` type for the cursor and the `htmlFor` prop based on the id that you provide. The label can be styled using the `style` or `className` prop like this:\n\n```jsx\n...\nimport CustomUploadButton from 'react-firebase-file-uploader/lib/CustomUploadButton';\n...\n  <CustomUploadButton\n    accept=\"image/*\"\n    storageRef={firebase.storage().ref('images')}\n    onUploadStart={this.handleUploadStart}\n    onUploadError={this.handleUploadError}\n    onUploadSuccess={this.handleUploadSuccess}\n    onProgress={this.handleProgress}\n    style={{backgroundColor: 'steelblue', color: 'white', padding: 10, borderRadius: 4}}\n  >\n    Select your awesome avatar\n  </CustomUploadButton>\n...\n```\n\nThis will result in the same rendered button as the [wrap example](#wrapping-the-input-in-a-label).\n\n### Generate a filename\n\nIf you would like to generate a filename yourself you can provide a function as `filename` attribute:\n\n```jsx\n...\n  <FileUploader\n    accept=\"image/*\"\n    name=\"avatar\"\n    filename={file => this.state.username + file.name.split('.')[1]; }\n    storageRef={firebase.storage().ref('images')}\n    onUploadStart={this.handleUploadStart}\n    onUploadError={this.handleUploadError}\n    onUploadSuccess={this.handleUploadSuccess}\n    onProgress={this.handleProgress}\n  />\n...\n```\n\nIn the example above, the filename is generated by is naively (do not use in production!) extracting the file extension from the selected file and placing it after the username, such that the resulting filename will be `johndoe.jpg` if the username were `johndoe` and the extension of the selected file `.jpg`.\n\n### Uploading multiple files\n\nIf you provide the `multiple` prop to the input, this will allow a user to select and upload multiple files at once. All callbacks will be called with the upload task as second argument. You can use this task to discriminate between the uploaded files, for example by using the path in `task.snapshot.ref.fullPath` as identifier for the upload.\n\nTry it on CodeSandbox\n\n[![Edit 30k0kx6k7m](https://codesandbox.io/static/img/play-codesandbox.svg)](https://codesandbox.io/s/30k0kx6k7m)\n\nOr just copy/paste from here:\n```jsx\nimport React from \"react\";\nimport ReactDOM from \"react-dom\";\nimport firebase from \"firebase\";\nimport FileUploader from \"react-firebase-file-uploader\";\n\n// Setup Firebase\nfirebase.initializeApp({\n  apiKey: \"API_KEY\",\n  storageBucket: \"PROJECT_ID.appspot.com\"\n});\n\nclass App extends React.Component {\n  state = {\n    filenames: [],\n    downloadURLs: [],\n    isUploading: false,\n    uploadProgress: 0\n  };\n\n  handleUploadStart = () =>\n    this.setState({\n      isUploading: true,\n      uploadProgress: 0\n    });\n\n  handleProgress = progress =>\n    this.setState({\n      uploadProgress: progress\n    });\n\n  handleUploadError = error => {\n    this.setState({\n      isUploading: false\n      // Todo: handle error\n    });\n    console.error(error);\n  };\n\n  handleUploadSuccess = async filename => {\n    const downloadURL = await firebase\n      .storage()\n      .ref(\"images\")\n      .child(filename)\n      .getDownloadURL();\n\n    this.setState(oldState => ({\n      filenames: [...oldState.filenames, filename],\n      downloadURLs: [...oldState.downloadURLs, downloadURL],\n      uploadProgress: 100,\n      isUploading: false\n    }));\n  };\n\n  render() {\n    return (\n      <div>\n        <FileUploader\n          accept=\"image/*\"\n          name=\"image-uploader-multiple\"\n          randomizeFilename\n          storageRef={firebase.storage().ref(\"images\")}\n          onUploadStart={this.handleUploadStart}\n          onUploadError={this.handleUploadError}\n          onUploadSuccess={this.handleUploadSuccess}\n          onProgress={this.handleProgress}\n          multiple\n        />\n\n        <p>Progress: {this.state.uploadProgress}</p>\n\n        <p>Filenames: {this.state.filenames.join(\", \")}</p>\n\n        <div>\n          {this.state.downloadURLs.map((downloadURL, i) => {\n            return <img key={i} src={downloadURL} />;\n          })}\n        </div>\n      </div>\n    );\n  }\n}\n\nconst rootElement = document.getElementById(\"root\");\nReactDOM.render(<App />, rootElement);\n```\n\n### Starting downloads manually\n\nIf you prefer triggering downloads manually (i.e. on a click of a button), rather than automatically when file(s) are selected, you can do so by overriding the default `onChange`event handler.\n\nTo do so, you have to save a `reference` to the component.\n\n```jsx\nclass MyAwesomeComponent extends React.Component {\n  state = {\n    files: [],\n  };\n\n  /**\n  * Custom onChange event handler\n  * Store selected files in the state\n  */\n  customOnChangeHandler = (event) => {\n    const { target: { files } } = event;\n    const filesToStore = [];\n\n    files.forEach(file => filesToStore.push(file));\n\n    this.setState({ files: filesToStore });\n  }\n\n  /**\n  * Start download handler using the file uploader reference\n  */\n  startUploadManually = () => {\n    const { files } = this.state;\n    files.forEach(file => {\n      this.fileUploader.startUpload(file)\n    });\n  }\n\n  render() {\n  ...\n    <FileUploader\n        ...\n        onChange={this.customOnChangeHandler} // ⇐ Call your handler\n        ref={instance => { this.fileUploader = instance; } }  // ⇐ reference the component\n    />\n    <button onClick={this.startUploadManually}>Upload all the things</button>\n    ...\n  }\n}\n```\n","readmeFilename":"README.md","_rev":"1-6dbfe636f437b391efb3ef461d1b13c1"}