Upload multiple images to separate folder in Next Js [duplicate] - reactjs

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!

Related

How to fix 'error - unhandledRejection: TypeError [ERR_INVALID_ARG_TYPE]: The "path" argument must be of type string. Received undefined'

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!

React-dropzone-uploader : 422 Unprocessable Entity with fastapi upload

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/*"
/>
)
}

How to upload files to AWS S3 bucket from the react frontend

Hello I am trying to upload images from my react frontend but its unable to read the file in axios and the images are not being uploaded.
This is my code.
<form onSubmit={Upload}>
<input
type='file'
onChange={(e) => {
generate(e.target.files);
}}
/>
<button type='submit'>Submit</button>
</form>
const generate = async (data) => {
const payload = {
entity: 'test',
userId: '200',
documentFileName: data[0].name,
action: 'putObject',
};
console.log('DAATA', data[0].name);
await api
.generatePreSignedUrl(payload, token)
.then((res) => {
setUploadUrl(res.data.data);
setImageData(data);
})
.catch((err) => {
console.log('Error', err);
});
};
const Upload = async (e) => {
e.preventDefault();
console.log('IMAGEdata', imageData);
console.log('URL', uploadUrl);
let file = imageData[0];
console.log('THIS IS FILE', file);
console.log('FILENAME', file.name);
console.log('FIELETYPE', file.type);
var options = {
headers: {
'Content-Type': file.type,
},
};
await axios
.put(uploadUrl, file, options)
.then((res) => {
console.log('Response from s3');
console.log(res);
})
.catch((error) => {
alert('ERROR ' + JSON.stringify(error));
});
};
Here imageUrl is the signed URL that I get from was to upload my files. I am successfully able to call the put request to upload the file but the image or file is not being read and uploaded.
This is the response when I am trying to look at the uploaded file.
This XML file does not appear to have any style information associated with it. The document tree is shown below.
<Error>
<Code>NoSuchKey</Code>
<Message>The specified key does not exist.</Message>
<Key>documents/ama/test/200/displaypicture.png</Key>
<RequestId>R7M63AHQKDNC6NH5</RequestId>
<HostId>3u8Jb8Ev4S1s/ODicL3Py4hvrvwKKOs/5zGxUEDYORfN1+U37Zx8PfYvIcGWUIAfeCqHpWqXd8o=</HostId>
</Error>
Look at the AWS SDK for JavaScript Developer Guide Version 3. There are examples that show how to upload photos to an Amazon S3 bucket.
Uploading photos to Amazon S3 from a browser
A pretty simple way to use this node module to achieve this:
https://www.npmjs.com/package/react-aws-s3
https://medium.com/#steven_creates/uploading-files-to-s3-using-react-js-hooks-react-aws-s3-c4c0684f38b3
enter image description here
npm install --save react-aws-s3
User " aws-sdk " and use this code
import React ,{useState} from 'react';
import AWS from 'aws-sdk'
const S3_BUCKET ='YOUR_BUCKET_NAME_HERE';
const REGION ='YOUR_DESIRED_REGION_HERE';
AWS.config.update({
accessKeyId: 'YOUR_ACCESS_KEY_HERE',
secretAccessKey: 'YOUR_SECRET_ACCESS_KEY_HERE'
})
const myBucket = new AWS.S3({
params: { Bucket: S3_BUCKET},
region: REGION,
})
const UploadImageToS3WithNativeSdk = () => {
const [progress , setProgress] = useState(0);
const [selectedFile, setSelectedFile] = useState(null);
const handleFileInput = (e) => {
setSelectedFile(e.target.files[0]);
}
const uploadFile = (file) => {
const params = {
ACL: 'public-read',
Body: file,
Bucket: S3_BUCKET,
Key: file.name
};
myBucket.putObject(params)
.on('httpUploadProgress', (evt) => {
setProgress(Math.round((evt.loaded / evt.total) * 100))
})
.send((err) => {
if (err) console.log(err)
})
}
return <div>
<div>Native SDK File Upload Progress is {progress}%</div>
<input type="file" onChange={handleFileInput}/>
<button onClick={() => uploadFile(selectedFile)}> Upload to S3</button>
</div>
}
export default UploadImageToS3WithNativeSdk;

React redux upload image with graphql and use of axios

When I try to upload image i getting an error:
xhr.js:177 POST http://localhost:3000/graphql 400 (Bad Request)
categoryAction.tsx:57 Error: Request failed with status code 400
at createError (createError.js:16)
at settle (settle.js:17)
at XMLHttpRequest.handleLoad (xhr.js:62)
When I upload From the postman upload successfuly but when try with react axios getting above error
My Form
const addForm = (props:any) => {
const [category,setCategory] = useState({
image:''
})
const onDataChange = (e:any,name:string,image:string) => {
let oldData : any = { ...category }
const imageFile = e.target.files[0];
oldData[image] = imageFile;
setCategory(oldData);
}
const onFinish = async (values : any) => {
let categoryData = {...category}
let formdata = new FormData();
formdata.append('image',categoryData.image);
await props.AddCategory(formdata);
console.log('Success:', values);
};
return (
<>
<Form>
<Form.Item
name="image"
label="Category Image"
>
<Input type="file" name="image" onChange={(e) => onDataChange(e,'image','image')} />
</Form.Item>
<Button type="primary" htmlType="submit" onClick={onFinish}> Submit </Button>
</Form>
</>
}
const mapDispatchToProps = (dispatch:any) => {
return {
AddCategory:(data:any) => dispatch(AddCategory(data))
}
export default connect(null,mapDispatchToProps)(addForm);
Now this is my Redux Action
export const AddCategory : any = (data:any) => {
return async (dispatch: Dispatch) => {
dispatch({
type:types.INIT_ADD_DATA
})
await axios.post(`http://localhost:3000/graphql`,
{
query: ` mutation {
addCategory(image: ${data}){
imagePath
}
}
`
})
.then((response) => {
dispatch({
type:types.ADD_DATA_SUCCESS,
myData: { data : response.data}
});
}).catch((error) => {
console.log(error)
dispatch({
type:types.ADD_DATA_FAILED,
error:error.message
});
})
};
};
My API IN Node Is
import { gql } from 'apollo-server'
const CategoriesTypeDef = gql`
extend type Mutation {
addCategory(image: Upload!): Category!
}
type Category {
categoryId: ID!
image: String!
}
`
while api through post data , data uploaded successfully but use of react typescript axios it will generate error how to fix it .

501 Not Implemented error in small web app

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,

Resources