Uploading posts via API is working just fine, but I am new to uploading images.
Any idea what I’m doing wrong? (404 error)
// Import the necessary modules
import axios from 'axios';
import fs from 'fs';
import FormData from 'form-data';
import dotenv from 'dotenv';
import GhostAdminAPI from '@tryghost/admin-api';
// Initialize dotenv
dotenv.config();
// Define Ghost Admin API key and URL
const GHOST_ADMIN_API_KEY = process.env.GHOST_ADMIN_API_KEY;
const GHOST_ADMIN_URL = process.env.GHOST_ADMIN_URL;
// Ensure all necessary environment variables are set
if (!GHOST_ADMIN_API_KEY || !GHOST_ADMIN_URL) {
console.error('ERROR: Missing necessary environment variables. Please set GHOST_ADMIN_API_KEY and GHOST_ADMIN_URL.');
process.exit(1);
}
// Function to upload the image
const uploadImageToGhost = async (imagePath) => {
try {
// Check if the file exists
if (!fs.existsSync(imagePath)) {
console.error('ERROR: The specified image file does not exist:', imagePath);
return;
}
// Create a new instance of FormData
const formData = new FormData();
// Add the image file to the form data
formData.append('file', fs.createReadStream(imagePath));
// Axios configuration for the POST request
const config = {
headers: {
'Authorization': `Ghost ${GHOST_ADMIN_API_KEY}`,
...formData.getHeaders() // Spread operator to merge form data headers
}
};
// Send POST request to Ghost API
const response = await axios.post(`${GHOST_ADMIN_URL}/images/upload/`, formData, config);
// Log the URL of the uploaded image
console.log('Image uploaded successfully. Image URL:', response.data.url);
} catch (error) {
console.error('An error occurred while uploading the image:', error);
}
}
// Call the function
uploadImageToGhost("./inputData/georgia.jpg");
It seems there is a JWT token error now (or always?). If anyone has a generic example of a node.js script that simply uploads one image to Ghost successfully, I would love to see it. I may be defeated on this one.
Random question, is this simply just not handled via the API?
It might be an authentication issue then, not a 404 error.
On that front, I see that you’re trying to use the GHOST_ADMIN_API_KEY directly in the Authorization header. However, you first need to create a JWT token from it, as outlined here.
I have modified your script a bit and tested it with one of my Ghost instances. It is working now
// Import the necessary modules
import axios from 'axios';
import fs from 'fs';
import FormData from 'form-data';
import dotenv from 'dotenv';
import GhostAdminAPI from '@tryghost/admin-api';
// Initialize dotenv
dotenv.config();
// Define Ghost Admin API key and URL
const GHOST_ADMIN_API_KEY = process.env.GHOST_ADMIN_API_KEY;
const GHOST_ADMIN_URL = process.env.GHOST_ADMIN_URL;
// Ensure all necessary environment variables are set
if (!GHOST_ADMIN_API_KEY || !GHOST_ADMIN_URL) {
console.error(
'ERROR: Missing necessary environment variables. Please set GHOST_ADMIN_API_KEY and GHOST_ADMIN_URL.'
);
process.exit(1);
}
// Split the key into ID and SECRET
const [id, secret] = GHOST_ADMIN_API_KEY.split(':');
// Create the token (including decoding secret)
const token = jwt.sign({}, Buffer.from(secret, 'hex'), {
keyid: id,
algorithm: 'HS256',
expiresIn: '5m',
audience: `/admin/`,
});
// Function to upload the image
const uploadImageToGhost = async (imagePath) => {
try {
// Check if the file exists
if (!fs.existsSync(imagePath)) {
console.error(
'ERROR: The specified image file does not exist:',
imagePath
);
return;
}
// Create a new instance of FormData
const formData = new FormData();
// Add the image file to the form data
formData.append('file', fs.createReadStream(imagePath));
// Axios configuration for the POST request
const config = {
headers: {
Authorization: `Ghost ${token}`,
...formData.getHeaders(), // Spread operator to merge form data headers
},
};
// Send POST request to Ghost API
const response = await axios.post(
`${GHOST_ADMIN_URL}/images/upload/`,
formData,
config
);
// Log the URL of the uploaded image
console.log(
'Image uploaded successfully. Image URL:',
response.data.images[0].url
);
} catch (error) {
console.error(
'An error occurred while uploading the image:',
error.response.data
);
}
};
uploadImageToGhost('./inputData/georgia.jpg');
Another note on it: based on this script you actually don’t need the @tryghost/admin-api module. You could, however, re-write the script to use it – might make things a bit easier in regards to the token generation (since that is handled for you), but add another dependency.
EDIT: @RyanF provided a great example on how to do this with the SDK – now you have two versions and can choose which one you prefer