We are using react dropzone uploader to upload video with fastapi's
UploadFile
function
Below is the code
const MyUploader = () => {
// called every time a file's `status` changes
const handleChangeStatus = ({ meta, file }, status) => { console.log(status, meta, file) }
// receives array of files that are done uploading when submit button is clicked
const handleSubmit = (files, allFiles) => {
files.map(file => uploadFile(file))
}
return (
<Dropzone
onChangeStatus={handleChangeStatus}
onSubmit={handleSubmit}
accept="video/*"
/>
)
}
and
function uploadFile (file) {
// Initial FormData
console.log("file inside uploadfile",file)
let formData = new FormData();
formData.append("file_obj", file);
const clientid=localStorage.getItem("client_id");
console.log("clientid",clientid)
return axios.post(`${apiEndpoint}/upload?clientId=${clientid}`, formData, {
headers: {
"Content-Type": "multipart/form-data",
},
});
}
below is the error getting
and backend code is
#router.post("/upload")
async def Videoupload(response: Response, clientId: str = None, file_obj: UploadFile = File(...)):
try:
if validate_filename(file_obj.filename):
response.status_code=409
return "video with filename already exists"
upload_video(clientId,file_obj)
response.status_code = 201
return "file uploaded"
except Exception as error:
print("Error in uploading", str(error))
response.status_code = 500
return "Error in uploading"
It could be great if anybody can help with this
Correct way of using RDU is to call upload api in
getUploadParams
const MyUploader = () => {
const getUploadParams = ({ file, meta }) => {
const body= new FormData()
body.append('file_obj', file)
const clientid=localStorage.getItem("client_id");
console.log("clientid",clientid)
return { url: `${apiEndpoint}/upload?clientId=${clientid}`, body }
}
// called every time a file's `status` changes
const handleChangeStatus = ({ meta, file }, status) => { console.log(status, meta, file) }
// receives array of files that are done uploading when submit button is clicked
const handleSubmit = (files, allFiles) => {
console.log(files.map(f => f.meta))
allFiles.forEach(f => f.remove())
}
return (
<Dropzone
getUploadParams={getUploadParams}
onChangeStatus={handleChangeStatus}
onSubmit={handleSubmit}
accept="video/*"
/>
)
}
Related
I have a task for uploading images using Next js. API for image uploading has been given and it exists in the same project and when it becomes successful images are stored in a separate directory.
API for image uploading is as follows,
import formidable from "formidable";
import path from "path";
import { renameSync } from "fs";
export const config = {
api: {
bodyParser: false,
},
};
export default async function upload(req, res) {
if (req.method !== "POST") {
return res.status(405).json({ error: "Method not allowed" });
}
const form = new formidable.IncomingForm({
keepExtensions: true,
maxFileSize: 200 * 1024 * 1024,
});
return new Promise((resolve, reject) => {
form.parse(req, async (err, fields, files) => {
if (err) {
res.status(500).json({ error: err.message });
return resolve();
}
if (!files.image) {
res.status(422).json({ error: "Bad request: missing image field" });
return resolve();
}
const ext = path.extname(files.image.path);
const uuid = Math.random().toString(26).slice(2);
await renameSync(files.image.path, `./public/images/${uuid}${ext}`);
res.status(201).json({
uuid,
url: `/images/${uuid}${ext}`,
});
return resolve();
});
});
}
Code for the front-end is mentioned below,
import React from "react";
export default function UploadImage() {
const [imgsSrc, setImgsSrc] = React.useState([]);
const uploadToClient = (e) => {
for (const file of e.target.files) {
setImgsSrc((imgs) => [...imgs, file]);
}
};
const uploadToServer = async () => {
let formData = new FormData();
for (const file of imgsSrc) {
formData.append('image', file, file.name)
}
const response = await fetch("/api/upload", {
method: "POST",
body: formData
});
};
return(
<div>
<h3>Upload photos</h3>
<input onChange={uploadToClient} type="file" name="file" multiple />
<div>
{imgsSrc.map((link) => (
<img src={link} style={{ width: 200, height: 200 }} />
))}
</div>
<button type="submit" onClick={uploadToServer}>Send to server</button>
</div>
)
}
When uploading images I am getting 'error - unhandledRejection: TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received undefined'.
Any suggestion would be highly appreciated!
Is there a way to delete all uploaded files at once? When I uploaded success. I want to call event remove all files. I didn't find any solution for this. Tks for all the help !
Here is my code:
upload file
const [fileDatas, setFileDatas] = useState([]);
const dummyRequest = ({ file, onSuccess }) => {};
const beforeUpload = (file, fileList) => {return false};
const { Dragger } = Upload;
const props = {
accept: 'image/png, image/jpeg, image/svg, image/gif, .xlsx,.xls,image/*,.doc, .docx,.ppt, .pptx,.txt,.pdf',
name: 'file',
multiple: true,
beforeUpload: beforeUpload,
action: dummyRequest,
onChange({ file, fileList }) {
if (file.status !== 'uploading') {
setFileUploads(fileList);
}
},
onDrop(e) {
console.log('Dropped files', e.dataTransfer.files);
setFileUploads(e.dataTransfer.files);
},
};
handle event submit upload file
const handleUploadFile = () => {
if (fileUploads.length === 0) {
toastActionWarning('No files to upload');
}else{
setFileUploads([]);
const formDatas = new FormData();
fileUploads.forEach((file) => {
formDatas.append(file.name, file.originFileObj);
});
axios
.post('files', formDatas, { withCredentials: true })
.then((res) => {
let newList = [...fileDatas];
res.data.data.forEach(element => {
element.author = window.userDisplayName;
newList = [element, ...newList]
});
setFileDatas(newList);
//I want to clear all file here
toastActionSuccess('Upload successfully');
})
.catch((error) => {
toastActionFailed('There was an error in processing');
});
}
};
I'm using react js version 17, I want to upload file and send it to my node js api.
I have two buttons, The first button used to read the first line in the file,
the second button is for the call to the back end server to save the file in the database as a file
I have create a formData to set my formData file input always i got empty object.
Here's my code :
const [myFile,setMyFile] = useState();
const [headers,setHeaders] = useState();
const readFile = e =>{
const file = e.target.files[0];
const reader = new FileReader();
reader.onload = function(e) {
const text = e.target.result;
const headers = text.slice(0,text.indexOf('\n')).split(';');
setHeaders(headers)
}
reader.readAsText(file);
setMyFile(file)
}
const callApi = e => {
const formData = new FormData();
formData.append(
"file",
myFile,
);
axios.post('localhost:8080/uploadFile', formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
})
}
My formData always return an empty object {}
Upload logic in react js to send csv in API to backend :
import React, { Component } from "react";
import axios from 'axios';
import AppContext from './AppContext';
const SERVER_URL = process.env.REACT_APP_SERVER_URL;
const PROTOCOL = process.env.REACT_APP_PROTOCOL;
const PORT = process.env.REACT_APP_PORT;
class UploadMeasure extends Component {
constructor() {
super();
this.state = {
csvfile: undefined
};
this.updateData = this.updateData.bind(this);
}
handleChange = event => {
this.setState({
csvfile: event.target.files[0]
});
};
importCSV = () => {
const { csvfile } = this.state;
console.log(csvfile);
var fileName = csvfile.name;
const formData = new FormData();
formData.append(
"fileChooser",
csvfile,
);
axios.post(PROTOCOL + "://" + SERVER_URL + ":" + PORT + "/uploadMeasures/" + AppContext.username + "?&fileName=" + fileName, formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(res => { // then print response status
console.log(res)
if (res === 'success') {
alert("File data uploaded Successfully");
} else {
if (res === 'Error') {
alert("Please ensure that your CSV file is formatted using the correct template, if you have any doubt contact the support team.");
} else {
console.log(res)
}
}
})
};
updateData(result) {
var data = result.data;
console.log(data);
}
render() {
console.log(this.state.csvfile);
return (
<div className="App">
<h2>Import CSV File!</h2>
<input
className="csv-input"
type="file"
ref={input => {
this.filesInput = input;
}}
name="file"
placeholder={null}
onChange={this.handleChange}
/>
<p />
<button onClick={this.importCSV}> Upload now!</button>
</div>
);
}
}
export default UploadMeasure;
My simplified code is below.
Goal: To display the names of the images that the user selects. The user selects an image, it is saved to a service, and I use a "put" request to get the images for that particular object, and then display the name. These steps are required for getting the names.
Issue: When I first select images via the "file upload button" (Form.Control), the image name(s) do not display on the #1 (commented as "#1: HERE!", at the bottom of code). When I go back and select more images, then #1 correctly displays the previously selected images AND the newly selected images (which is the correct behavior). My problem is that on the first selection, the image name is NOT being displayed.
const MyComponent = () => {
const [fileNames, setFileNames] = useState({});
// a service that calls gets the file names from objectId
const getFileNames = (objectId) => {
const input = { objectId: objectId };
fetch(service(), {
method: "PUT",
headers: {..(stuff here), "Content-Type": "application/json"},
body: JSON.stringify(input)
})
.then( res => { res.json() })
.then( resJson => {
if( //resJson has errors) {
//log error msg
else {
// problem is here????
setFileNames(resJson.results);
return resJson;
}
})
.catch( err => //stuff here)
}
const handleFileChange = (e) => {
// saves selected file(s) to particular objectId
saveFile(event.target.files), props.objectId, props.somethingelse);
getFileNames(props.objectID);
}
const showName = (file) => {
return (
<span> {file.name} </span>
)
}
return (
<div>
<Form.Control
type="file" multiple
onChange={ e=> {handleFileChange(e)} }
{/* bunch of the stuff here */}
/>
{/* ***********#1 - HERE!*************** */}
{fileNames.map( file => file.showName(file) )}
</div>
)
}
I suspect you are not waiting for the file to be saved before you get the filename. That's why perhaps the first save is empty?
const MyComponent = () => {
const [fileNames, setFileNames] = useState([]);
// This should be an array be default since you map over it later down
// make this an async function
const getFileNames = async (objectId) => {
const input = { objectId: objectId };
let resJson;
try {
const result = await fetch(service(), {
method: 'PUT',
headers: { 'Content-Type': 'application/json' },
body: JSON.stringify(input),
});
resJson = await result.json();
} catch (error) {
// TODO: error handling
}
if (resJson.error) { // TODO: fix me
//log error msg
} else {
setFileNames(resJson.results);
}
};
// this too should be an asnyc function
const handleFileChange = async (event) => {
// I assume saveFile is an async function
await saveFile(event.target.files, props.objectId, props.somethingelse);
// save the file here ^ and wait for it to finish saving
await getFileNames(props.objectID);
// after you saved the file get the filename now
};
const showName = (file) => {
return <span> {file.name} </span>;
};
return (
<div>
<Form.Control
type="file"
multiple
onChange={(e) => {
handleFileChange(e);
}}
/>
{/* bunch of the stuff here */}
{fileNames.map((file) => file.showName(file))}
</div>
);
};
I am trying to upload images to an S3 bucket with react and expressjs. When I attempt to upload the image I get a 501 Not Implemented Error. I am using axios to contact the end point I created in the server code.
My react code:
class FileUpload extends Component {
state = {
file: null
};
submitFile = (event) => {
event.preventDefault();
const formData = new FormData();
formData.append('file', this.state.file[0]);
axios.post(`test-upload`, formData, {
headers: {
'Content-Type': 'multipart/form-data'
}
}).then(response => {
// handle your response;
}).catch(error => {
// handle your error
});
}
handleFileUpload = (event) => {
this.setState({file: event.target.files});
}
render () {
return (
<form onSubmit={this.submitFile}>
<input label='upload file' type='file' onChange=
{this.handleFileUpload} />
<button type='submit'>Send</button>
</form>
);
}
}
export default FileUpload;
My server code:
const uploadFile = (buffer, name, type) => {
const params = {
ACL: 'public-read',
Body: buffer,
Bucket: process.env.S3_BUCKET,
ContentType: type.mime,
Key: `${name}.${type.ext}`
};
return s3.upload(params).promise();
};
app.use('/', (req,res) =>{
res.send(JSON.stringify({ greeting: `Hello!` }));
});
// Define POST route
app.post('/test-upload', (request, response) => {
const form = new multiparty.Form();
form.parse(request, async (error, fields, files) => {
if (error) throw new Error(error);
try {
const path = files.file[0].path;
const buffer = fs.readFileSync(path);
const type = fileType(buffer);
const timestamp = Date.now().toString();
const fileName = `bucketFolder/${timestamp}-lg`;
const data = await uploadFile(buffer, fileName, type);
return response.status(200).send(data);
} catch (error) {
return response.status(400).send(error);
}
});
});
This was done by following a guide on the internet but there seems to be something missing that I just can't figure out.
Figured it out in the end,
axios.post(/test-upload,
should have been
axios.post(http://localhost:3000/test-upload,