I have a problem with fetch and Ionic 6. It is not sending image data to the server.
The code is as follows:
let formData = new FormData();
formData.append('photo', pathImage);
fetch(this.MAIN_URL + '/uploadAvatar?token=' + token, { method: 'POST', body: formData})
.then(response => response.json())
.then(data => {
alert(JSON.stringify(data));
})
.catch(error => {
alert(JSON.stringify(error));
})
Thing is, the image data is not being sent to the server. The variable pathImage comes from Ionic's Crop plugin, and it is like this:
file:///storage/emulated/0/Android/data/io.ionic.starter/cache/(random_number).jpg
I think it is not getting the data from pathImage, but how can I change that? I tried turning pathImage into a blob but that didn't work either.
After doing some research, here is the answer to my question:
let formData = new FormData();
const file = await Filesystem.readFile({ path: pathImage.split('?')[0] });
let blob = new Blob([this.fixBinary(atob(file.data))], { type: 'image/jpeg' });
formData.append('photo', blob);
fetch(this.MAIN_URL + '/uploadAvatar?token=' + token, { method: 'POST', body: formData})
.then(response => response.json())
.then(data => {
alert(JSON.stringify(data));
})
.catch(error => {
alert(JSON.stringify(error));
})
Where fixBinary is a function that fixes the binary data coming from the jpg file:
fixBinary (bin: any) {
var length = bin.length;
var buf = new ArrayBuffer(length);
var arr = new Uint8Array(buf);
for (var i = 0; i < length; i++) {
arr[i] = bin.charCodeAt(i);
}
return buf;
}
Now, if I pick and crop a file, the end result is uploaded to the server just fine.
Related
I have the following code, where I have an array of images images and uploading each image in that array. the code is working fine, but I have an issue, where all the uploaded images have the same name ex: storage/1671621889.png.
const uploadData = async (data) => {
const attachment = []
const url = `http://127.0.0.1:8000/api/file/upload`
const config = {
headers: {
'content-type': 'multipart/form-data'
}
}
await Promise.all(images.map(async (file, index) => {
const imageData = new FormData()
imageData.append('file', file)
imageData.append('fileName', file?.name)
let result
axios.post(url, imageData, config)
.then(function(response) {
result = response.data.data.file
attachment.push(result)
})
}))
.then(() => {
submit(data, attachment)
})
}
I tried awaiting the request, but that doesn't change anything.
You're defining your upload file name already as file?.name. If you must make it unique for each request, you can simply append the index.
const uploadData = async (data) => {
const attachment = []
const url = `http://127.0.0.1:8000/api/file/upload`
const config = {
headers: {
'content-type': 'multipart/form-data'
}
}
await Promise.all(images.map(async (file, index) => {
const imageData = new FormData()
imageData.append('file', file)
imageData.append('fileName', `${file?.name}_${index}`)
let result
axios.post(url, imageData, config)
.then(function(response) {
result = response.data.data.file
attachment.push(result)
})
}))
.then(() => {
submit(data, attachment)
})
}
I'm trying to send images from my form to my php webservice.
For now, I'm just trying to see if i receive it well.
and with this code:
html:
<input type="file" multiple name="images" id="images" />
<button class="bouton" id="valider">envoi</button>
Js:
const sample_image = document.getElementById('images');
const valider = document.getElementById('valider');
valider.addEventListener('click', () => {
upload_image(sample_image.files[0]);
})
const upload_image = (file) => {
const form_data = new FormData();
form_data.append('sample_image', file);
console.log(form_data);
fetch(host+"add.php", {
method: "POST",
body:form_data
}).then(response => response.json())
.then(response => {
console.log(response);
});
}
Php:
echo json_encode($_FILES['sample_image']);
It's working but only for 1 image, but i need send many.
and when i try to change my JS to :
upload_image(sample_image.files);
(without the [0])
it's not working.
I just wanted to send an array of files and then use it in my php, but it says
Notice: Undefined index: sample_image
Does it exists a way to do it ?
Thank you.
it's working with :
const upload_image = (files) => {
const form_data = new FormData();
let compt = files.length;
for(let i=0;i<compt;i++)
{
form_data.append('sample_images[]', files[i]);
}
console.log(files.length);
console.log(form_data);
fetch(host+"add.php", {
method: "POST",
body:form_data
}).then(response => response.json())
.then(response => {
console.log(response);
}); }
thank you everyone !
You need to change the FormData to receive an array instead of a single item:
const upload_image = (files) => {
const form_data = new FormData();
form_data.append('sample_images[]', files);
console.log(form_data);
fetch(host+"add.php", {
method: "POST",
body:form_data
}).then(response => response.json())
.then(response => {
console.log(response);
}); }
I am using firebase to storage my 5 jpegs.
I need to download them and pass them to function to retrieve EXIF data from them.
To accomplish that tash i have made bellow script which is:
checking how many files are in specific folder in database
getting download url's for every file
looping through every url and executing function wchich is downloading files from those url's
The problem is: first four images are downloaded properly. The last one is allways not downloaded completelly.
Please see bellow code. Note fucntion called getHTML1 is redundant do getHTML, and gives the same result.
I just tried different approach.
TLDR:
How to make fetch wait for last file being completelly downloaded?
import {
getStorage,
ref,
listAll,
getDownloadURL
} from "firebase/storage";
const storage = getStorage();
const listRef = ref(storage, 'images');
const firebaseDownloadHandler = async() => {
function getHTML1(url) {
return new Promise(function(resolve, reject) {
var xhr = new XMLHttpRequest();
xhr.open('get', url);
xhr.responseType = 'blob';
xhr.onload = function() {
var status = xhr.status;
if (status === 200) {
let blob = new Blob([xhr.response], {
type: 'image/jpeg'
})
console.log(xhr.response);
resolve(blob);
} else {
reject(status);
}
};
xhr.send();
});
}
function getHTML(url) {
return new Promise(async function(resolve, reject) {
await fetch(url, {
method: 'GET',
type: 'image/jpeg'
})
.then(res => res.blob())
.then(blob => {
resolve(blob)
});
})
}
const res = await listAll(listRef);
const requests = res.items.map(itemRef => getDownloadURL(itemRef))
const urls = await Promise.all(requests);
const processArray = async() => {
console.log(urls);
const finalResult = [];
return new Promise(async function(resolve, reject) {
for (let i = 0; i < urls.length; i++) {
const result = await getHTML(urls[i + 1]);
finalResult.push(result);
if (finalResult.length === urls.length) {
resolve(finalResult);
}
}
})
};
const downloaded = await processArray();
return await downloaded;
}
export default firebaseDownloadHandler;
result:
20:06:11.499
Array(5) [ "https://firebasestorage.googleapis.com/v0/b/geolocf.appspot.…025.jpg?alt=media&token=8ecbfc6d-07ed-4205-9599-a6e36dd444ed", "https://firebasestorage.googleapis.com/v0/b/geolocf.appspot.…028.jpg?alt=media&token=06a422fa-64f2-482f-9f63-c39aaf1d9354", "https://firebasestorage.googleapis.com/v0/b/geolocf.appspot.…855.jpg?alt=media&token=6ae03b2c-bd82-49fc-bcb6-0de0683e7d50", "https://firebasestorage.googleapis.com/v0/b/geolocf.appspot.…402.jpg?alt=media&token=a22ef4dd-7f79-40aa-90df-57ad73b10248", "https://firebasestorage.googleapis.com/v0/b/geolocf.appspot.…646.jpg?alt=media&token=e04958d0-ed2f-44f6-9931-18644ffbe8b8" ]
firebaseDownloadHandler.js:45
20:06:14.882
Array(5) [ Blob, Blob, Blob, Blob, Blob ]
0: Blob { size: 6428869, type: "image/jpeg" }
1: Blob { size: 7402504, type: "image/jpeg" }
2: Blob { size: 2858717, type: "image/jpeg" }
3: Blob { size: 3045876, type: "image/jpeg" }
4: Blob { size: 2278, type: "text/html; charset=utf-8" }
length: 5
<prototype>: Array []
I'm not sure if this is the cause of the problem, but you're overusing custom promises.
As far as I can see, this function:
function getHTML(url) {
return new Promise(async function(resolve, reject) {
await fetch(url, {
method: 'GET',
type: 'image/jpeg'
})
.then(res => res.blob())
.then(blob => {
resolve(blob)
});
})
}
Can be shorted to this without any change in functionality:
function getHTML(url) {
return fetch(url, {
method: 'GET',
type: 'image/jpeg'
})
.then(res => res.blob())
}
Yeah. Error is not caused by fetch itself.
I wrongly passed urls to fetching function.
Should be
const result = await getHTML(urls[i]);
Instead of
const result = await getHTML(urls[i + 1]);
I've tried the imgbb-uploader npm package but I only got it to work with other image URLs and not local files.
axios
.post("https://api.imgbb.com/1/upload", {
image: BASE_64_STRING,
name: file.name,
key: process.env.MY_API_KEY,
})
.then((res) => console.log(res))
.catch((err) => console.log(err));```
What about this:
// fileinput is the file/index 0 from input-type-file eg: e.target.myfileinput.files[0]
const uploadImg = ( fileinput ) => {
const formData = new FormData();
formData.append( "image", fileinput ); // has to be named 'image'!
let apiresponse = axios.post( 'https://api.imgbb.com/1/upload?key=your-api-key', formData )
.then( res => { return res.data } )
.catch( error => { return null } )
return apiresponse;
}
//From graph ql perspective
const { createReadStream, filename } = await file;
const url = "<URL_TO_IMAGE_SERVER&key=<YOUR_API_KEY>";
const stream = createReadStream();
const form = new FormData();
form.append("image", stream, filename);
try {
const response = await axios.post(url, form, {
headers: { ...form.getHeaders() },
});
console.log({ response });
return { Location: response.data.display_url };
} catch (error) {
return { ...error };
}
My Goal is to upload an image taken from a webcam to a Lambda function which then uploads it to AWS S3.
The lambda function seems to work when I test it, however I can't work out what exactly needs to be sent through from the React Camera.
Or if I am sending through the right format to upload it.
import Camera from 'react-camera';
..
This is the JSX
<Camera
ref={(cam) => {
this.camera = cam;
}}
>
<Button onClick={this.takePicture}>
<i className="fas fa-camera"></i> Take photo
</Button>
</Camera>
This is the react code that is called when they take the photo
takePicture = () => {
this.camera.capture()
.then(blob => {
console.log(blob);
this.props.dispatch(uploadImage(blob))
})
}
The uploadImage function in my action is:
export const uploadImage = (fileObj) => dispatch => {
return fetch(url, {
method: 'POST',
headers: {
'Accept': 'image/jpeg'
},
body: fileObj
})
.then((response) => response.json())
.then(function (response) {
if (response.status === 'success') {
console.log(response);
// ... Show feedback
return response
} else {
// ... Show feedback
}
})
.catch((error) => {
console.error(error)
});
}
I figure I need to upload a base64 image..?
I don't understand how I get that from the blob
Here is the Lambda Function code for reference:
var params = {
Bucket: 'bucketName',
Key: Date.now() + '.jpg',
ContentType: 'image/jpeg',
Body: event.body,
ACL: "public-read"
};
return uploading = new Promise(function (resolve, reject) {
return s3.upload(params, function (err, data) {
if(err) {
state.uploadError = err
return reject({
error: err,
status: 'error',
message: 'something went wrong'
})
}
state.uploadData = data
state.fileLocation = data.Location
state.status = "success"
state.message = "File has been uploaded to the fileLocation"
return resolve(data)
});
})
Question:
How do I make the format of the blob correct so that when it's POSTed though as the body it will be the correct image format?
Very well organized question and code... thank you!
Updated:
Use the filesystem module to read the file and specify the encoding.
const fs = require('fs');
takePicture = () => {
this.camera.capture()
.then(blob => {
console.log(blob);
const image = fs.readFileSync(blob.path);
const b64Image = Buffer.from(image).toString('base64');
this.props.dispatch(uploadImage(b64image));
})
}