I am VERY new to reactJS and I am trying to create a simple web app that allows me to upload a file and then save that file to my projects directory.
I have tried browserify-fs but its doesn't seem to create the file when I use fs.writeFile
The below code allows me to upload a file but I am struggling to save the file in my project directory
import ReactDOM from 'react-dom';
import Dropzone from 'react-dropzone';
class App extends Component {
onDrop = (acceptedFiles) => {
// Save acceptedFiles in this scripts directory
}
render() {
return (
<Dropzone onDrop={this.onDrop}>
{({getRootProps, getInputProps}) => (
<div {...getRootProps()}>
<input {...getInputProps()} />
Click me to upload a file!
</div>
)}
</Dropzone>
);
}
}
export default App;
ReactDOM.render(
<App />,
document.getElementById('root')
);
browserify-fs stores data in the browser (I'm assuming using local storage, but I can't find a clear statement to that effect).
If you want to store data on the server then you'll need to:
Send the data to the server (using Ajax)
Store that data using server-side code
Use the following function...
function download(content, fileName, contentType) {
var a = document.createElement("a");
var file = new Blob([content], {type: contentType});
a.href = URL.createObjectURL(file);
a.download = fileName;
a.click();
}
...and call as follows...
download('Text to Save to the File', 'TestSave.txt', 'text/plain')
Related
I am new to react. A task assigned to create drag and drop component. I followed some blogs to do the task, which only accept image file types. Now the task is when clicked on the upload icon it should open file explorer which should only show image type files. I cannot try to figure out how that would work. Part of my codes which i took from various blogs are:
Drag and drop component:
import React from "react";
import { useDropzone } from "react-dropzone";
import UploadIcon from '#mui/icons-material/Upload';
const Dropzone = ({ onDrop, accept }) => {
// Initializing useDropzone hooks with options
const { getRootProps, getInputProps, isDragActive } = useDropzone({
onDrop,
accept
});
/*
useDropzone hooks exposes two functions called getRootProps and getInputProps
and also exposes isDragActive boolean
*/
return (
<div className="dropzone-div" {...getRootProps()}>
<input className="dropzone-input" {...getInputProps()} accept=".gif,.jpg,.jpeg,.png"/>
<div className="text-center">
<UploadIcon fontSize="large"/>
{isDragActive ? (
<p className="dropzone-content"> Release to drop the files here</p>
) : (
<p className="dropzone-content">
<b> Choose a file </b> or drag it here
</p>
)}
</div>
</div>
);
};
export default Dropzone;
In the app.js
import React, { useCallback,useState } from "react";
import './App.css';
import Form from './components/Form';
import DragDrop from './components/DragDrop';
import ImageList from "./components/ImageList";
import cuid from "cuid";
function App() {
const [images, setImages] = useState([]);
const [errorMessage, setErrorMessage] = useState([]);
const onDrop = useCallback(acceptedFiles => {
// Loop through accepted files
acceptedFiles.map(file => {
// Initialize FileReader browser API
if (!file.name.match(/\.(jpg|jpeg|PNG|gif|JPEG|png|JPG|gif)$/)) {
setErrorMessage('please select valid file image');
//this.setState({ invalidImage: 'Please select valid image.' });
return false;
}
if(file.name.match(/\.(jpg|jpeg|PNG|gif|JPEG|png|JPG|gif)$/)){
const reader = new FileReader();
// onload callback gets called after the reader reads the file data
reader.onload = function(e) {
// add the image into the state. Since FileReader reading process is asynchronous, its better to get the latest snapshot state (i.e., prevState) and update it.
setImages(prevState => [
...prevState,
{ id: cuid(), src: e.target.result }
]);
setErrorMessage();
};
// Read the file as Data URL (since we accept only images)
reader.readAsDataURL(file);
}
return file;
});
}, []);
return (
<main className="App">
<h2 className="App">Drag and Drop Example</h2>
<br />
<div className=".dropzone-div">
<DragDrop onDrop={onDrop} accept={ 'image/*'}/>
</div>
<div className="App">
{errorMessage && <span> {errorMessage} </span>}
<ImageList images={images} />
</div>
</main>
);
}
export default App;
Use an input element with the type as file, like so:
<span>
<label for="upload">Upload</label>
<input id="upload" type="file" accept="image/*" />
</span>
You could of course change the label to your liking, such as an upload icon.
This is a native HTML element that comes with the functionality you want, out of the box. It is tempting to code everything by hand, especially if you're a beginner. Just remember to search for native solutions before you try a new functionality, or even better, familiarize yourself with the docs of the language/framework you're using.
By the way, here's the MDN doc for the file input element: https://developer.mozilla.org/en-US/docs/Web/HTML/Element/input/file
Basically, I will try to use tsparticles JSON file in my react project that I export from https://particles.js.org/. but it was not working.
I have used particle js in my project. In my project, I have made a separate component and called this component inside the main component like the App.js
And I have made the JSON file as an API. If you want to make the JSON file into an API or also you can directly call this API.
import React from "react";
import Particles from "react-tsparticles";
import { loadFull } from "tsparticles";
const ParticleAnimation = () => {
const particlesInit = async (main) => {
console.log(main);
await loadFull(main);
};
const particlesLoaded = (container) => {
console.log(container);
};
return (
<div>
<Particles
id="tsparticles"
url={YOUR_JSON_FILE_LINK_HERE}
init={particlesInit}
loaded={particlesLoaded}
/>
</div>
);
};
export default ParticleAnimation;
I want to create react js drag and drop file upload using class component !!
I have tried the normal file upload and it works fine, in addition I have tried using the react-drag-drop library, I can't access the file properties !!
react-dropzone uses React hooks to create HTML5-compliant React components for handling the dragging and dropping of files. react-dropzone provides the added functionality of restricting file types and also customizing the dropzone.
To install
npm install --save react-dropzone
Example of drag-and-drop component
import React, {useEffect, useState} from 'react';
import {useDropzone} from 'react-dropzone';
function App(props) {
const [files, setFiles] = useState([]);
const {getRootProps, getInputProps} = useDropzone({
accept: 'image/*',
onDrop: acceptedFiles => {
setFiles(acceptedFiles.map(file => Object.assign(file, {
preview: URL.createObjectURL(file)
})));
}
});
const thumbs = files.map(file => (
<div style={thumb} key={file.name}>
<div style={thumbInner}>
<img
src={file.preview}
style={img}
/>
</div>
</div>
));
useEffect(() => {
// Make sure to revoke the data uris to avoid memory leaks
files.forEach(file => URL.revokeObjectURL(file.preview));
}, [files]);
return (
<section className="container">
<div {...getRootProps({className: 'dropzone'})}>
<input {...getInputProps()} />
<p>Drag 'n' drop some files here, or click to select files</p>
</div>
<aside style={thumbsContainer}>
{thumbs}
</aside>
</section>
);
}
export default App
I can load csv files from external URL, but when I try to load a file that the user uploaded to the web, it shows an empty Object.
The object appears to be loaded, but you can`t access the information in any way. The solutions I found online were to setup servers, but I didn't want to do that. I want to have an client-side only web app with tensorflowJS.
main.js:
export default function Main() {
const [archivo, setArchivo] = useState();
const cargarArchivo = (archivo) => {
setArchivo(archivo);
};
async function realizarCalculos() {
await preprocesamiento(archivo);
}
return (
<div>
<Dropzone cargarArchivo={cargarArchivo} />
<Button
onClick={realizarCalculos}
style={{ margin: "5vh" }}
variant="outlined"
>
Calcular Caudales
</Button>
</div>
);
}
Dropzone.js:
class Dropzone extends Component {
constructor(props) {
super(props);
this.state = {
files: [],
};
}
handleChange(files) {
this.props.cargarArchivo(files[0]);
this.setState({
files: files,
});
}
render() {
return (
<DropzoneArea
acceptedFiles={[".csv"]}
onChange={this.handleChange.bind(this)}
/>
);
}
}
export default Dropzone;
Tensorflow JS:
import * as tf from "#tensorflow/tfjs";
export async preprocesamiento(archivo){
const csvDataset = tf.data.csv(archivo.path);
}
TensorflowJS tf.data.csv works with fetch under the hood. Meaning that you can't load local files, see this question. I resolved the issue by creating an URL object with the URL class, and serving the url to tensorflow :
import * as tf from "#tensorflow/tfjs";
export async preprocesamiento(archivo){
const url = URL.createObjectURL(archivo);
const csvDataset = tf.data.csv(url);
}
I want to be able to select multiple files and send them to my backend but can't figure out how.
In app.js I have a usestate that I send as a prop to my file upload-component.
But after selectig the files I get FileList() with correct number of entries but they are all undefined in my file-state.
If I change the onChange function to :
(e) => setFiles(e.target.files[0])
or any other index I get a correct file. But how do I save the whole file-array directly?
And in the next step when I need to post my files to the backend can I access them by filename or do I need to store them as blobs or byte-arrays to be able to send them in a json-format?
import React from "react";
export const FileUpload = ({ files, setFiles }) => {
return (
<div className="file-upload">
<span className="button">
<i className="material-icons">attachment</i>Choose files
</span>
<input
type="file"
multiple
className="multiple-files"
aria-label="Multiple file upload"
accept="image/*"
onChange={(e) => setFiles(e.target.files)}
/>
</div>
);
};
After some trial and error I came up with this solution:
const fileHandler = e => {
const fileArray = Array.from(e.target.files)
fileArray.map(f => f["id"] = Math.random() * Math.pow(10,16))
setFiles(fileArray)
}