Uploading images from react with laravel api - reactjs

I'm having trouble uploading files from a react input using a laravel API.
I'm working with react-hook-form.
My form and onSave are as follows
const onSave = data => {
// data.picture = imgs; here I tried changing the picture to event.target.files from the file input, didn't work either.
axios.defaults.headers.common["Authorization"] = "Bearer " + token;
axios
.post(`/api/products/store`, data, {})
.then(res => {
console.log(res);
})
.catch(err => console.log(err));
};
return (
<form onSubmit={handleSubmit(onSave)} encType="multipart/form-data">
<input
type="file"
name="picture[]"
label="Product Picture"
onChange={handlePicInput}
className={classes.inputFile}
multiple
/>
//other inputs
</form>
);
my post request leads to this controller method
public function store(Request $request)
{
$imageNames = '';
$pictures = (object) $request->file('picture');
//$pictures = $request->allFiles();
//$pictures = (object) $request->file('picture[]');
//$pictures = (object) $request->files;
foreach ($pictures as $key => $picture) {
/*WHEN I'M USING POSTMAN OR INSOMNIA,
this foreach loop is accessed but
the react form just skips the foreach completely */
$imageNames = $imageNames . $picture->store('product_pictures', 'public') . ',';
}
$product = Product::create([
'name' => $request->name,
'prices_amountmax' => $request->prices_amountmax,
'prices_amountmin' => $request->prices_amountmax,
'brand' => $request->brand,
'manufacturer' => $request->manufacturer,
'weight' => $request->weight,
'category_id' => $request->category_id,
'stock' => $request->stock,
'imageurls' => $imageNames
]);
$product->save();
}
To sum up, I tested uploading images with postman, it works just fine, so the problem must be in the react form?
Thank you for any kind of help

To upload images using js you can use FormData. I can't see your handlePicInput method to understand how input change is handled, but may be this snippet can help you to understand what to do further.
function handlePicInput(event){
let images = event.target.files
let fd = new FormData()
fd.append("images", images);
}
Then you can append to fd your other values and send via axios
axios.post(`/api/products/store`, fd)
Again, where to place the code and how to handle other inputs you have to manage by yourself, or provide more data

Try sending it as formData, with multiple files:
const onSave = data => {
const formData = new FormData();
for (let i in data) {
if(i === 'picture[]'){
for(let file of data[i]){
formData.append('picture',file);
}
}else{
formData.append(i, data[i])
}
}
// data.picture = imgs; here I tried changing the picture to event.target.files from the file input, didn't work either.
axios.defaults.headers.common["Authorization"] = "Bearer " + token;
axios
.post(`/api/products/store`, formData, {})
.then(res => {
console.log(res);
})
.catch(err => console.log(err));
};
I tested it with my Node/Express backend and it seems to work. "picture" will be an array of files. If your php backend doesn't recognize this correctly, try changing the formData.append('picture',file) to formData.append('picture[]',file), but then you'll also need to change the name in your php.

Related

how can i delete multiples request at the same time using axios and an array of URL

im doing an app and the first code is working deleting a "task" in my API, but in my app each task have a checkbox input, so, i want to delete all the tasks that are checked.
i used this code to delete single task with a button.
const baseURLtasksId = `https://63cf2168e52f5878299ab5e2.mockapi.io/api/users/${userid}/tasks/${taskId}`
axios.delete(baseURLtasksId, { done: true }).then()
}
ArrayUrlById this is an array of all the URL's that are checked
const deleteAll = () => {
let ArrayUrlById = []
ArrayUrlById = isChecked.map((cId) => {
let arrayURL = `https://63cf2168e52f5878299ab5e2.mockapi.io/api/users/${userid}/tasks/${cId}`
return arrayURL
})
console.log(ArrayUrlById); // here i have an array of the URL
// i need to delete now multiples tasks, using an array of URL and sending {done:true} for each one
}
i tried with this code, but not working properly, beacuse never delete all of them, even in the console send all the delete request to the endpoint with a 200 status, but after i refresg the website, is not deleting all of them that are checked
const deleteAll = () => {
let ArrayUrlById = []
console.log('aqui');
ArrayUrlById = isChecked.map((c) => {
let arrayURL = `https://63cf2168e52f5878299ab5e2.mockapi.io/api/users/${userid}/tasks/${c}`
return arrayURL
})
console.log(ArrayUrlById);
const requests = ArrayUrlById.map(url => axios.delete(url));
axios.all(requests)
.then(responses => {
responses.forEach(response => console.log(response.data));
})
.catch(error => {
console.log(error);
})
}
enter image description here

issue while uploading multiples images to firebase storage

I am trying to upload multiples images to firebase storage , using react native for an android project , once images got uploaded I should get back download urls .
I have tested 2 methods, first one , upload is fine , but as result I got only download urls of last item.
second method , no upload , neither download urls has succeded, could you please help and correct my code , here is my code :
my first method :
const [downloadUrls , setDownloadUrls] = useState([])
const [images , setImages] = useState([])
useEffect(()=>{
if(downloadUrls !== null) {
console.log(downloadUrls , 'urlx');
}else{
console.log('no downloadUrls')
}
},[images, selectedIndex,downloadUrls ]);
...
let filename;
let imageRef;
let promise1;
let promise2;
let task = storage();
if(images !== null){
images.map( async (item , index)=>{
// uri = item;
filename = item.substring(item.lastIndexOf('/') + 1);
imageRef = storage().ref(filename);
if(imageRef){
setUploading(true)
}
// uploading images
await imageRef.putFile(item).then(()=> {setUploading(false), setImageCounter((p) => p+1 )
} ).catch((error) => { console.log('error22') }) ;
// get back download urls
await imageRef.getDownloadURL().then((img) => setDownloadUrls((previouse) => [...previouse, img])).catch((error) => { console.log(error) });
})
//setImages([])
}
in my secod test , I've tried to work with promises but it failed , no upload , no download urls,
here is my code :
let filename;
let imageRef;
let promise1;
let promise2;
let task = storage();
if(images !== null){
images.map( async (item , index)=>{
filename = item.substring(item.lastIndexOf('/') + 1);
imageRef = storage().ref(filename);
if(imageRef){
setUploading(true)
}
promise1 = new Promise((resolve , reject) =>{
imageRef.putFile(item);
resolve(()=>{
setUploading(false);
});
reject((e) =>{
console.log(e)
})
});
promise2 = new Promise((resolve , reject) =>{
imageRef.getDownloadURL();
resolve((e)=>{
setDownloadUrls( (urls ) => [...urls , e])
})
reject((e) => console.log(e))
})
//setImages([])
Promise.all([promise1, promise2])
}
thank you for your help

React Laravel - File showing in state but not in controller

My project has React as frontend and Laravel as backend.
I am trying to upload a file and the details of the file appear in state while uploading but not in the controller and hence not able to upload it in folder.
Component has
<div className="form-group col-sm-4">
<div className="imgPreview">{$imagePreview}</div>
<label>Profile Pic</label>
<input className="form-control" type="file" name="profile_pic" onChange={(e)=>this._handleImageChange(e)}/>
</div>
further codes are:
_handleImageChange(e) {
e.preventDefault();
let reader = new FileReader();
let file = e.target.files[0];
reader.onloadend = () => {
this.setState({
fileselected: file,
profile_pic: file.name,
imagePreviewUrl: reader.result
});
}
reader.readAsDataURL(file)
}
Data gets uploaded though axios
submitHandler = e =>{
e.preventDefault()
this.props.drprofilecreate(this.state)
}
export const drprofilecreate = (data) => dispatch =>{
console.log("Coming form profile create action ")
console.log(data)
return axios.post('/api/v1/drProfileCreate', data)
.then( res =>res.data )
.then(drprofile =>
dispatch({
type: DRPROFILECREATE,
payload: drprofile,
}),
)
}
When I view the data being uploaded, it shows the file with its details like name, size etc. But the same does not come in the controller. It shows a blank array.
public function drProfileCreate(Request $request){
$data = $request->all();
$response = [
'success' =>true,
'datax' =>'Dr Profile uploaded in Contorller. Check',
'data' => $data
];
return response()->json($response, 201);
}
Hence Iam not able to upload the image. Help please. Appreciated

MERN+ Cloudinary: Unsupported source URL

I'm trying to upload file to cloudinary. Here is part of my react component
...
addItem() {
...
let file = this.fileInput.value;
keywords !== "" && this.props.onAddItem(keywords, place, image);
...
}
render() {
return (
....
<Input
type="file"
innerRef={(input) => {this.fileInput = input}}
name="image"
id="image"
placeholder=""/>
)
}
Here is action file:
export function onAddItem(keywords, place, file, id, isChangebale = false) {
return (dispatch) => {
axios.all([
axios.post('https://api.cloudinary.com/v1_1/myservername/image/upload',
{upload_preset: "mypresetname", file: file}),
axios.post('http://localhost:3001/api/items/', { keywords, place, id, isChangebale })
])
.then(axios.spread((cloudinaryRes, localRes) => {
console.log(cloudinaryRes, localRes);
}))
I receive error xhr.js:178 POST https://api.cloudinary.com/v1_1/testovich/image/upload 400 (Bad Request) and in response headers "X-Cld-Error: Unsupported source URL: C:\fakepath\2017-12-07_19-06-445.png"
When I test using postman I have correct response.
So it looks like I do something wrong when pass file from rect component to action file. How to pass correct path/file to cloudinary?
There were two mistakes:
1. in react component there should be
let file = this.fileInput.files[0];//I upload only one file
instead of
let file = this.fileInput.value;
in action file
export function onAddItem(keywords, place, image, id, isChangebale = false) {
const formData = new FormData();
formData.append("file", image);
formData.append("upload_preset", "mypresetname");
return (dispatch) => {
axios.all([
// AJAX upload request using Axios )
axios.post('https://api.cloudinary.com/v1_1/myservername/image/upload',
formData,
instead of:
export function onAddItem(keywords, place, file, id, isChangebale = false) {
return (dispatch) => {
axios.all([
axios.post('https://api.cloudinary.com/v1_1/myservername/image/upload',
{upload_preset: "mypresetname", file: file}),
Convert the image to a base64 like const base64Img = data:image/jpg;base64,${file.data};
The file.data represents the data property from response from image picker.
Then I passed the base64Img to data like
return RNFetchBlob.fetch('POST', apiUrl, headerProps, [ { name: 'file', fileName: file.fileName, type: file.type, data: base64Img } ]);
Hope it helps.

Confused on blob:url and converting it to base64 in react-dropzone

I am using the package react-dropzone (https://github.com/okonet/react-dropzone) to get images from the user. The user uploads their image and everything is fine, but Im only getting something like "blob:http//blahblah" from it and I need the image to be in base64 png.
my dropzone component:
<Dropzone ref="dropzone" multiple={false} onDrop={this.onDrop.bind(this)} >
{this.state.files ?<img className="img-responsive" src={this.state.files[0].preview}></img>
: <div>Upload Photo</div> }
</Dropzone>
and the drop function that gets the blob url :
onDrop (files ) {
if ( files.length === 0 ) {
alert("upload img please")
return;
}
console.log('Received files: ', files);
this.setState({files:files})
var blobURL = files[0].preview
var reader = new FileReader();
reader.readAsDataURL(blobURL)
}
I would get an error :Uncaught TypeError: Failed to execute 'readAsDataURL' on 'FileReader': parameter 1 is not of type 'Blob'.
I think it is because im trying to pass in an object-url that points to a blob, but where would I be able to get blob so I can convert to base64?
I would suggest to use a promise to get the result of async convertion by FileReader.readAsDataURL method. Here's the sample how it can be done:
const promise = new Promise((resolve, reject) => {
const reader = new FileReader()
reader.readAsDataURL(files[0])
reader.onload = () => {
if (!!reader.result) {
resolve(reader.result)
}
else {
reject(Error("Failed converting to base64"))
}
}
})
promise.then(result => {
// dispatch or do whatever you need with result
}, err => {
console.log(err)
})

Resources