Sanity.io API upload images from URL - instagram

Cross post from slack#help channel...
I'm creating a Sanity/Nuxt site for a client that includes a blog component. His primary marketing source is Instagram and since Instagram's API only allows for single-image posts I'm trying to go about it in the reverse way. I'm setting up a Netlify function where the client will paste in the link to the Instagram post and the function will fetch all associated images via URL using the /?__a=1 trick to fetch public data from Instagram. What I would like to do is fetch all of the images from said Instagram post, upload them as assets, and then create a blog post utilizing said uploaded images. I've modified the built-in Netlify function to create a Sanity document, where I'm pulling the image as an arrayBuffer, converting it to 'base64', then trying to upload.
When I try to run the file, found at https://gist.github.com/jeffpohlmeyer/d9824920fc1eb522ceff6380edb9de80 , I get the following error:
body: {
statusCode: 400,
error: 'Bad Request',
message: 'Invalid image, could not read metadata',
details: 'Input buffer contains unsupported image format'
},
Can anyone suggest a way I can do this? As an alternative I figured I could just link to the URLs hosted on Instagram instead of hosting the images within Sanity but it makes it difficult to maintain for the client if, for example, the Instagram post changes or he wants to change the cover image, choosing URLs instead of images would be difficult.

Tried the same on my repl:
async function uploadImage(){
const image = await axios.get(
'<<url>>',
{ responseType: 'arraybuffer' }
)
const data = Buffer.from(image.data, 'binary');
client.assets
.upload('image', data)
.then(() => {
console.log('Done!')
})
.catch((err) => {
console.log('err', err)
return { statusCode: 400 }
})
}
uploadImage();
just remove base64 conversion done and this should work

Related

Pass image ArrayBuffer to Azure Face SDK detectWithStream()

I am trying to write a NodeJS app that grabs a image from private URL using Axios and passes it to the Azure Face SDK (documentation) to detect faces in the image and get attributes of those faces - in this case, emotions and head pose.
I have gotten a modified version of the quickstart example code here working, which makes a call to the detectWithUrl() method. However, the image that I have in my code is a ArrayBuffer, so I thought I would try calling detectWithStream() instead. The documentation for this method says it needs to be passed something of type msRest.HttpRequestBody - I found some documentation for this type, which looks like it wants to be a Blob, string, ArrayBuffer, or ArrayBufferView. The problem is, I don't really understand what those are or how I might get from a arraybuffer image to an HttpRequestBody of that type. I have worked with HTTP requests before, but I don't quite understand why one is being passed to this method, or how to make it.
const rqs = {
responseType: 'arraybuffer',
url: `${fileUrl}`,
method: 'GET',
headers: {
'Content-Type': `image/jpeg`,
'Cache-Control': 'no-cache'
},
httpsAgent: agent
};
axios.request(rqs)
.then((ret) => {
// ret.data is a ArrayBuffer type;
let detected_faces = client.face.detectWithStream(ret.data, {
returnFaceAttributes: ["Accessories", "Age", "Blur", "Emotion", "Exposure", "FacialHair", "Glasses", "Hair", "HeadPose", "Makeup", "Noise", "Occlusion", "Smile", "QualityForRecognition"],
detectionModel: "detection_01",
recognitionModel: "recognition_03"
})
.then(ok => {
console.log(ok);
console.log("face(s) detected from image.");
console.log("Face attributes for face(s):");
})
.catch(err => {
console.error(err.message);
});
console.log('ok');
resolve(ret.data);
})
.catch((err) => {
console.error('nok');
console.error(err.message);
reject(false)
});
And I had receive a message error Only absolute URLs are supported
Only absolute URLs are supported -
a. it may be due to passing relative URL to Axios in line 3, try checking the fileUrl.
b. check the face SDK is provided with the proper endpoint
relative URL - "./a/b"
absolute URL - "https://www.x.com/a/b"
how I might get from an array buffer image?
Array buffer is not needed. Looking at face SDK code Ref (hope this is right sdk), we just need streams.
we can get this by changing the responseType value to stream
responseType: 'arraybuffer', // current
responseType: 'stream', // updated - we can update it in rqs and reponse will be stream and you can pass res.data to detectWithStream function
-------------------------------------Hope the code works----------------------------------------
Recommendation:
You are creating a callback hell by using nested .then chains what is call back hell.
Try using async/await syntax to achieve the same functionality in a simplified way - Ref.
Regards,
Muhamed

My response is not an url, How can I display an image which is not url using base64 and response does not contain bodyBytes?

My api is get() and the response contains data like this
The above image which you can see is my image which I want to display it on web using reactjs. ANd I dont know how can this be done.
The get api returns data, config, headers, request, status,statusText
I want the data above which I some weird format, my image to be displayed. I dont know how to do it. Need help
Update:
action
export const getFileImage = (payload) => async dispatch => {
try {
console.log("Payload--->",payload);
let response = await axios.get('/api/movies/' + payload.movieId + '/document/' + payload.genre.toLowerCase().toString());
console.log("Response----->",response);
} catch (error) {
console.log("error");
}
}
Output of response:
OK, you asked for an example and I wrote this answer...
You can use base64 format to show Images in your React component:
render(){
{this.state.image ? <img src={`data:image/png;base64,${this.state.image}`}/>: ''}
}
I think it would be better to ask backend developer or API provider to convert output for web and your requirements in React JS.

Getting a bad request 400 when trying to upload zipped wkt file to here-maps rest api

We have a problem with the fleet.ls.hereapi.com when uploading a new layer for geofencing.
const myId = 'MYLAYER'; // just a id to check
zip.file('data.wkt', `NAME\tWKT\n${myId}\t${wkt}`);
const content = await zip.generateAsync({ type: 'nodebuffer' });
const formData = new FormData();
formData.append('zipfile', content);
await axios.post(config.HERE_MAPS_UPLOAD_ENDPOINT, formData, {
headers: {
'content-type': 'multipart/form-data',
},
params: {
apiKey: config.HERE_MAPS_REST_API_KEY,
layer_id: myId,
},
});
We get a bad request without a message and do not know what the problem is. The same implementation works in the Frontend (with 'blob' as zip type). Is there a parameter to get a better error message from the api?
We got the instructions how to implement it from this tutorial: https://www.youtube.com/watch?v=Ayw9GcS1V-8 and as I mentioned it works fine in the frontend. Also it works if I write a file in node and upload it via curl. Thank you for any help in advance!
Edit: I'm getting the following issue from the API: 'Multipart should contain exactly one part but contains 0'
I fixed it!
The problem was that the api needed a filename for the form data. This filename can be provided as third parameter as described here.
So I basically changed formData.append('zipfile', content); to formData.append('zipfile', content, zipfile.zip); and it worked.
Hope this will help somebody in the future!

How to get JSON from REACT JS to implement in NODE js

I am trying implement REST API using REACT AND NODE. How to get JSON from front end(REACT JS)drag and drop images in template ex."https://www.canva.com/templates/" to store JSON in Mongodb using NODE JS.
Thanks in advance
You can use fetch api to call a particular route and send data along with it to nodejs backend.
You just need to do simply like this:
async function sendData(){
let res = await fetch(url, {
method: 'POST',
mode: 'CORS',
body: {}, //the json object you want to send
headers: {}, //if required
}
)
}
Hope this helps!
Since you asked how to send JSON to node.js I'm assuming you do not yet have an API that your front end can use.
To send data to the back end you need to create an API that accepts data.
You can do this quickly and easily using express.js.
Once the server is running and it has an endpoint to send data to, you can create a request (e.g. when sending data it should be a POST request).
This can be done in many different ways, although I would suggest trying axios.
Hope this helped.
Check the example to get the Json value and update it.
axios.get('https://jsonplaceholder.typicode.com/todos/'+ this.props.id + '/')
.then((res) => {
this.setState({
// do some action
});
})
.catch(function (error) {
console.log(error);
});

NodeJS/React: Taking a picture, then sending it to mongoDB for storage and later display

I've been working on a small twitter-like website to teach myself React. It's going fairly well, and i want to allow users to take photos and attach it to their posts. I found a library called React-Camera that seems to do what i want it do to - it brings up the camera and manages to save something.
I say something because i am very confused about what to actually -do- with what i save. This is the client-side code for the image capturing, which i basically just copied from the documentation:
takePicture() {
try {
this.camera.capture()
.then(blob => {
this.setState({
show_camera: "none",
image: URL.createObjectURL(blob)
})
console.log(this.state);
this.img.src = URL.createObjectURL(blob);
this.img.onload = () => { URL.revokeObjectURL(this.src); }
var details = {
'img': this.img.src,
};
var formBody = [];
for (var property in details) {
var encodedKey = encodeURIComponent(property);
var encodedValue = encodeURIComponent(details[property]);
formBody.push(encodedKey + "=" + encodedValue);
}
formBody = formBody.join("&");
fetch('/newimage', {
method: 'post',
headers: {'Content-type': 'application/x-www-form-urlencoded;charset=UTF-8'},
body: formBody
});
console.log("Reqd post")
But what am i actually saving here? For testing i tried adding an image to the site and setting src={this.state.img} but that doesn't work. I can store this blob (which looks like, for example, blob:http://localhost:4000/dacf7a61-f8a7-484f-adf3-d28d369ae8db)
or the image itself into my DB, but again the problem is im not sure what the correct way to go about this is.
Basically, what i want to do is this:
1. Grab a picture using React-Camera
2. Send this in a post to /newimage
3. The image will then - in some form - be stored in the database
4. Later, a client may request an image that will be part of a post (ie. a tweet can have an image). This will then display the image on the website.
Any help would be greatly appreciated as i feel i am just getting more confused the more libraries i look at!
From your question i came to know that you are storing image in DB itself.
If my understanding is correct then you are attempting a bad approcah.
For this
you need to store images in project directory using your node application.
need to store path of images in DB.
using these path you can fetch the images and can display on webpage.
for uploading image using nodejs you can use Multer package.

Resources