How to upload images from Next.js to Sanity - node.js

I have been working on a project using next.js and sanity but I can't seem to find a way to upload images to Sanity. I have been following the Sanity tutorial on how to upload assets and it works only if I set the filepath manually or if the assets are in the same project folder.
Below is the sanity method I have been using the upload the files.
const filePath = '/Users/mike/images/bicycle.jpg'
client.assets
.upload('image', createReadStream(filePath), {
filename: basename(filePath)
})
.then(imageAsset => {
return client
.patch('some-document-id')
.set({
theImageField: {
_type: 'image',
asset: {
_type: "reference",
_ref: imageAsset._id
}
}
})
.commit()
})
.then(() => {
console.log("Done!");
})
The main issue for me is the onchange handler returns a fake path which I understand is due to browser security and for images to successfully upload there should be an actual filepath like C:/Users/user/downloads/image.jpg instead of C:/fakepath/image.jpg
I have also attempted to change the onChange handler to get the filename only but I still can't upload the images because of the filepath issue.
const [image, setImage] = React.useState(null)
function handleImage(e){
const selectedFile = e.target.files[0]
if(selectedFile){
return setImage(selectedFile.name)
}
}
I have tried to use formidable but I didn't succeed as well. Please assist with a method on how to upload images.

Related

Saving React Blob Images in Node Not Working

Here is images coming in request ( from react app)
req.body = {
imageData: [ 'blob:http://localhost:3000/0bdca87f-47dc-4e56-94ae-ea24e86b6530' ]
}
Now I need to save this on ImageKit ( Node.Js)
imagekit
.upload ({
file : req.body.imageData[0], // not working
// file : 'convert_blob_to_base64' // not working either
fileName: 'my_file_name1.jpg'
})
.then (response => {
console.log (response);
})
.catch (error => {
console.log (error);
});
It does save the image but corrupted one, I tried by converting blob to base64, then also it didn't worked out.
if I directly convert the image to base64 using https://www.base64encode.org/ site and use that code as file : 'base_64_directly_encoded_image' then it works
Do I need to store the images first on Node. Js Something, Can Any one guide please.

Cannot GET image url multer (NodeJS)

I am using multer library for file uploads on my React/NodeJS website.
This is the upload route on the backend:
var upload = multer({storage});
router.post('/events/upload', upload.single('image'), async (req, res) => {
try {
const fileName =req.file.filename;
const basePath = `${req.protocol}://${req.get('host')}/public/upload`
let event = new Event({
title: req.body.title,
description: req.body.description,
image: `${basePath}${fileName}`
})
event = await event.save()
if (!event) {
return res.status(400).send("Error in upload!")
}
return res.status(200).send(event)
} catch(error) {
console.log(error)
return res.status(500).send()
}
})
After I hit this endpoint, image successfully gets uploaded to public/uploads and the 'url' generated looks like this - http://localhost:5000/public/uploadv-a-i-b-h-a-v-.-j-p-g-1628524045320.jpeg
Now, I want to use the image url from the db to display to the client. But, when I access this url it says:
Cannot GET /public/uploadv-a-i-b-h-a-v-.-j-p-g-1628524045320.jpeg
How can I display the uploaded image to the client? Is there any other way to achieve this?
As you mentioned image uploaded successful in public folder.
Then it means you have not served public folder in express I think.
app.use('/public',express.static('public'))
Add the above code before your express routing code to make it work.
Please check this express static doc link.
Now you can access the public folder.

Upload image from React Native to Apollo Server not working?

I have created my backend with Nodejs and Apollo Server. I am trying to upload an image from my React Native client. Here is my backend code
Mutation: {
async singleUpload(_, { fileInput: { file, fileName } }) {
try {
const { createReadStream, filename, mimetype } = await file;
const stream = createReadStream();
const path = `./upload/${filename}`;
const tempFile = { id: 123, filename, mimetype, path };
await new Promise((resolve, reject) => {
const writeStream = createWriteStream(path);
// When the upload is fully written, resolve the promise.
writeStream.on("finish", resolve);
// If there's an error writing the file, remove the partially written file
// and reject the promise.
writeStream.on("error", (error) => {
unlink(path, () => {
reject(error);
});
});
// In node <= 13, errors are not automatically propagated between piped
// streams. If there is an error receiving the upload, destroy the write
// stream with the corresponding error.
stream.on("error", (error) => writeStream.destroy(error));
// Pipe the upload into the write stream.
stream.pipe(writeStream);
});
...then upload it to Firebase Storage
When I use Altair plugin for Firefox browser to upload image , it works fine.
Now for my React Native client, I am using apollo-upload-client lib. After a user picks image using the Image Picker plugin for React Native , I am creating a file
const file = new ReactNativeFile({
uri: image.uri,
type: image.type,
name: 'Hi there',
});
ReactNativeFile is from apollo-upload-client lib. Now when I upload it I get an error saying from my backend saying TypeError: createReadStream is not a function which I understand as there is no createReadStream parameter in my ReactNativeFile
so I decided to change my backend code to something like this
const { name, type } = await file;
console.log("Mime" + type);
const stream = fs.createReadStream(name);
fs module is from nodejs
Now when I try uploading image from Altair or from React Native , I get an error saying
[Error: ENOENT: no such file or directory,
Due to my lack of knowledge of backend I am not sure what is causing the issue.
I think if I try uploading it from ReactJS instead of React Native, my code might work for the backend.
But the image picker for browser and native mobile are very much different and I have not tried doing with ReactJS for now
I am following this article https://moonhighway.com/how-the-upload-scalar-works for my backend code

trying to share pdf, using react-native-share v2.0.0

react-native application version:
react-native#0.61.2
react-navive-share#2.0.0
rn-fetch-blob#0.11.2
server with version:
html-pdf#2.2.0
i'm trying to make application that can create pdf by send data into nodejs.
and currently i already manage to create pdf from nodejs.
Now i already can share the pdf using whatsapp/gmail, but the file that i share have an alien language in it, i will share the picture below. (locally it works fine)
below are my code so far:
my api at nodejs :
router.route('/fetchpdf').get((req, res) => {
const filePath = path.resolve(`${__dirname}/../../pdfquotation/${req.query.fileid}.pdf`);
res.sendFile(filePath)
})
RNFetchBlob.config(configOptions)
.fetch('GET', `http://domainName.com/api/pdf/fetchpdf?fileid=${fileid}`)
.then(resp => {
filePath = resp.path();
return resp.readFile('base64');
})
.then(async base64Data => {
base64Data = `data:${type};base64,` + base64Data;
await SharePDF.open({ url: base64Data, title: 'title here' });
});
and the result that i got from this are :
could someone pointing out, what should i do to fix this?
thanks

Upload images into a file server and store the url to the image using nodejs

I am implementing a web app using MEAN Stack and Angular 6. There I want to submit a form with file upload. '.png' files should be uploaded.
I want to save the file in a different file server and send the url to the image.Currently I upload files into a folder in my project and save the image in db (I used ng2fileupload and multer for that.). Then it saves like this.
"data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAV4AAAFUCAYAAABssFR8AAAK..."
But I want to save the image url and the image should be retrived by the url. Does anyone can explain a proper method for that?
I faced the same problem a month ago and find out a solution to this problem. Though I haven't used multer in the app.
From my frontend, I will be sending an object to Node API endpoint /event which will look like:-
let img = {
content: "data:image/png;base64,iVBORw0KGgoAAAANSUhEUg...",
filename: 'yourfile.png'
}
At the backend, I'm using Cloudinary to store my images (Its free plan allows 10GB storage) and returns secure https URLs. So install it using npm i cloudinary and require in your api.js file.
And add the below configuration
cloudinary.config({
cloud_name: 'yourapp',
api_key: 'YOUR_KEY',
api_secret: 'YOUR_SECRET_KEY'
});
Last Step:- (Not so optimized code)
Let say I have an event Schema which has images array, where I'll be storing the URLs returned by cloudinary.
app.post('/event', (req, res) => {
try {
if (req.body.images.length > 0) {
// Creating new Event instance
const event = new Event({
images: [],
});
// Looping over every image coming in the request object from frontend
req.body.images.forEach((img) => {
const base64Data = img.content.split(',')[1];
// Writing the images in upload folder for time being
fs.writeFileSync(`./uploads/${img.filename}`, base64Data, 'base64', (err) => {
if (err) {
throw err;
}
});
/* Now that image is saved in upload folder, Cloudnary picks
the image from upload folder and store it at their cloud space.*/
cloudinary.uploader.upload(`./uploads/${img.filename}`, async (result) => {
// Cloudnary returns id & URL of the image which is pushed into the event.images array.
event.images.push({
id: result.public_id,
url: result.secure_url
});
// Once image is pushed into the array, I'm removing it from my server's upload folder using unlinkSync function
fs.unlinkSync(`./uploads/${img.filename}`);
// When all the images are uploaded then I'm sending back the response
if (req.body.images.length === event.images.length) {
await event.save();
res.send({
event,
msg: 'Event created successfully'
});
}
});
});
}
} catch (e) {
res.status(400).send(e);
}
});
P.S. Go ahead and suggest some optimization solution for this code here

Resources