I am working on a react-native social app and trying to upload a post image from react-native using react-native-image-picker and typescript. I am able to get Image uri but have to create file/blob to send it to node js backend
const choosePhotoFromLibrary = async () => {
await launchImageLibrary({
mediaType: "photo",
selectionLimit: 1,
includeBase64: true
})
.then(({assets}: any) => {
setImage(assets[0].uri);
setFile(assets[0])
})
.catch((err) => {
console.log(err);
});
};
This is my react-native-image-picker function to select image from gallery. I have tried to convert uri to blob and then to file like
const blobuploadImage = async (imageUri) => {
const response = await fetch(imageUri);
const blob = await response.blob();
console.log(blob)
return blob;
};
const uploadImage = async () => {
const formData = new FormData();
const blob = await blobuploadImage(base.uri);
var file = new File([blob], `Image.${base.type.split("/")[1]}`, {
type: base.type,
});
formData.append("file", file);
return await dispatch(uploadFile({ token, formData }))
};
Image file is empty or corrupted that stored on backend but I have tested backend Api with postman uploading Image. Its working fine then
Tried to convert uri to blob and then to file and sending it to backend but image is empty or corrupted
const formData = new FormData();
formData.append("file", {
uri: file?.uri,
type: file?.type,
name: file?.fileName,
size: file?.fileSize,
});
Now I have use this method and now file is getting save on backend but still it giving typeError
Argument of type '{ uri: any; type: any; name: any; size: any; }' is not assignable to parameter of type 'string | Blob'.
Plz tell how to fix this typeError
Related
I am using react and nestjs to convert a html template to pdf format. So far I can convert html to pdf in the backend using puppeteer and send an array buffer to frontend. When I try to convert the array buffer into pdf in the frontend for some reason the pdf opens but it shows a table that says 'Failed to load PDF document'.
Backend code
async downloadPlan() {
const page = await this.browserContext.newPage();
const content = await page.goto('https://developer.mozilla.org/en-US/docs/Web/JavaScript/Guide/Keyed_collections', {
waitUntil: 'networkidle2'
});
console.log('content', content);
const pdf = await page.pdf({ format: 'A4', path: 'lcs.pdf', printBackground: true, scale: 0.5 });
this.browserContext.close();
return pdf;
}
Frontend Code
function getPDF(): any {
return axios.get(`http://localhost:4000/test/pdf`, {
responseType: 'arraybuffer',
headers: {
'Accept': 'application/pdf'
}
})
}
async function savePdf() {
return getPDF()
.then((response: any) => {
console.log(response);
const blob = new Blob([response.data], {type: 'application/pdf'})
const link = document.createElement('a')
link.href = window.URL.createObjectURL(blob)
link.download = `your-file-name.pdf`
link.click()
})
}
This is a MERN app that has a form consisting of text inputs and a file input. The problem: I am unable to access the file input in my backend.
Start of controller function:
async function create(req, res) {
function base64_encode(file) {
let bitmap = fs.readFileSync(file)
return bitmap.toString('base64')
}
console.log(req.file)
let image = base64_encode(req.file.path)
The console.log of req.file returns "undefined" and I get error message "Cannot read properties of undefined (reading 'path')" referring to req.file.path.
The route:
const multer = require("multer")
const upload = multer({ dest: '../../uploads/'})
router.post("/", upload.single('image'), spotCtrl.create)
It should be noted that the image file is not showing up in the image folder I created.
The handleSubmit function:
handleSubmit = async () => {
let chosenImage = this.state.image
const formdata = new FormData()
formdata.append('image', chosenImage)
let body = {
name: this.state.name,
description: this.state.description,
address: this.state.address
}
let options = {
method: 'POST',
body: JSON.stringify(body),
formdata: formdata
}
await fetch("/api", options)
.then(res => res.json())
}
The <form tag has encType="multipart/form" set as well.
I've installed multer, fs, express-fileupload, among others
A couple maybe relevant lines from my server.js:
app.use(express.json(), expressfileupload());
app.use(express.static(path.join(__dirname, 'build')));
I have tried in my controller function to use req.files instead of req.file however I get the same result.
I am getting a GraphQL error "Error: Cannot return null for non-nullable field ImageType.name." when I try to upload an image to the backend.
In the client I am using React, #apollo/client for the frontend, storing the images in Cloudinary before passing the payload sent back from Cloudinary server to store in my backend.
For some reason the profileImageUpload method is not receiving the name prop and is throwing an error.
Here is the code below
Here is my image type defs
const {
GraphQLObjectType,
GraphQLID,
GraphQLString,
GraphQLSchema,
GraphQLList,
GraphQLNonNull,
GraphQLEnumType,
GraphQLBoolean,
} = require("graphql");
// Image Type
const ImageType = new GraphQLObjectType({
name: "ImageType",
fields: () => ({
id: { type: GraphQLID },
name: { type: new GraphQLNonNull(GraphQLString) },
}),
});
Here is my Edit.js file where I am uploading from
let name, url;
const [
profileImageUpload,
{ data: imageData, loading: loadingImageData, error: errorImageData },
] = useMutation(PROFILE_IMAGE_UPLOAD, {
variables: {
id,
name,
},
});
const handleUpdateProfileImage = async () => {
try {
//append image to FormData
const form_data = new FormData();
form_data.append("file", imageHolder);
form_data.append("upload_preset", process.env.REACT_APP_UPLOAD_PRESET);
// Save image to cloudinary
const response = await axios.post(
`https://api.cloudinary.com/v1_1/${process.env.REACT_APP_CLOUD_NAME}/image/upload`,
form_data
);
// Here is the response after saving image to Cloudinary
console.log(response);
name = response.data.original_filename;
url = response.data.url;
//Loging values correctly
console.log({ id, name });
----->HERE IS WHERE THE PROBLEM IS, NAME IS NOT PARSED TO profileImageUpload method
await profileImageUpload(id, name);
console.log({ id, name });
console.log("Image Successfully sent to backend for handling");
// })
} catch (error) {
console.log(error);
}
};
And here is the error
Error: Cannot return null for non-nullable field ImageType.name.
at new ApolloError (index.ts:58:1)
at QueryManager.ts:246:1
at both (asyncMap.ts:30:1)
at asyncMap.ts:19:1
at new Promise (<anonymous>)
at Object.then (asyncMap.ts:19:1)
at Object.next (asyncMap.ts:31:1)
at notifySubscription (module.js:132:1)
at onNotify (module.js:176:1)
at SubscriptionObserver.next (module.js:225:1)
const handleSubmit =async (values)=>{
try{
const imageUri =values.images[0];
const filename =imageUri.substring(imageUri.lastIndexOf('/')+1);
const response = await fetch(values.images[0]);
const blob = await response.blob();
var imageURLs="";
firebase.storage().ref().child("images/"+filename).put(blob)
.on('state_changed' , (snapshot) => {
},
(error) => console.log(error)
);
}catch(e){
console.log("error",e);
}
}
in this function, the image was successfully added to the storage. I need to get the image download URL to store it in the listings collection
firebase.firestore().collection('listings')
.add({
id:uuid.v4(),
title: values.title,
price: values.price,
description: values.description,
category: values.category['label'],
image:imageURLs, //this is download url of the image
createdAt: new Date(),
supplierId:user.uid
})
If you don't need to watch the progress of the upload you can just use then to get the downloadURL when the upload is finished:
firebase
.storage()
.ref()
.child("images/" + filename)
.put(blob)
.then((snapshot) => {
snapshot.ref.getDownloadURL().then((url) => {
console.log("downloadURL", url);
});
});
I am trying to send a picture to the back end, the web api works when I test it with postman. The image file is empty when I send it from the front end.
this code bellow sending from form data
const submit = useCallback(
async (values: PostExtensions) => {
debugger;
setLoading(true);
const date = dayjs(values.date );
values.date = dayjs(date , "YYYY-MM-DDTHH:mm:ss Z").format();
var imgdata = values.file![0];
const formdata: FormData = new FormData();
formdata.append("postId", values.postId!);
formdata.append("file", imgdata);
formdata.append("userId", values.userId!);
formdata.append("projectId", values.projectId!);
formdata.append("date", values.date!);
for (var pair of Array.from(formdata.entries())) {
console.log(pair[0] + ', ' + JSON.stringify(pair[1]));
}
await entitySubmit({ // entity submit is axios extensions for my crud op and state op.
values: formdata,
dispatch: dispatch,
returndata: true,
links: [
{
type: 0,
link: "gider/addpost",
actionType: ActionType.add_Post,
method: "POST",
},
{
type: 1,
link: "gider/editpost",
actionType: ActionType.edit_Post,
method: "POST",
},
],
id: "postId",
})
.then((res) => {
if (res) {
console.log(res);
setLoading(false);
setShow({ ...show, modal: false });
} else {
setLoading(false);
}
})
.catch(() => setLoading(false));
return null;
},
[show, dispatch]
);
The file comes into values.file, but it turns into this shape when sending it.
file field always get this --> file, "[object Object]"
I could'nt post file object to server
EDIT 1: I found the solution, when I try this code
var imgdata = new Blob([values.file![0]], {type : 'image/jpeg'}),
it seems like work, but What if the image is not jpg extension?