Cannot send cloudinary public_id and url to backend - Next JS - javascript

I am making an expense tracker and accounting app for my client. I have added a file input and upload those file to cloudinary and store public_id and secure_url in backend and database. I am using Next JS for frontend and backend. I am getting following errors.
I have added unsigned upload_preset here is the image of my cloudinary settings page.
One more thing this code works some time and don't show this error instead it mood change and shows error that I have not provided public_id or secure_url in backend database.
here is the code:
Frontend:
const handleSubmit = async (e) => {
e.preventDefault();
const form = e.currentTarget;
const miningInput = Array.from(form.elements).find(
({ name }) => name === "miningPapers"
);
const miningFormData = new FormData();
for (const file of miningInput.files) {
miningFormData.append("file", file);
}
miningFormData.append("upload_preset", "mining-papers");
const miningRes = await axios.post(
"https://api.cloudinary.com/v1_1/cloudName/image/upload",
miningFormData
);
const insuranceInput = Array.from(form.elements).find(
({ name }) => name === "insurancePapers"
);
const insuranceFormData = new FormData();
for (const file of insuranceInput.files) {
insuranceFormData.append("file", file);
}
insuranceFormData.append("upload_preset", "insurance-papers");
const insuranceRes = await axios.post(
"https://api.cloudinary.com/v1_1/cloudName/image/upload",
insuranceFormData
);
const insurancePubId = insuranceRes.data.public_id;
const insuranceUrl = insuranceRes.data.secure_url;
const miningPapersPubId = miningRes.data.public_id;
const miningUrl = miningRes.data.secure_url;
dispatch(
create(
//Other Data
//ERROR here \/
{
insurancePapers: {
public_id: insuranceRes.data.public_id,
url: insuranceRes.data.secure_url,
},
},
//ERROR here \/
{
miningPapers: {
public_id: miningRes.data.public_id,
url: miningRes.data.secure_url,
},
},
)
)
}
Dispatch function:
export const create = (insurancePapers, miningPapers)=> async(dispatch)=>{
dispatch({ type: ADD_DISPATCH_REQUEST });
const { data } = await axiosInstance.post(`/api/dispatch/create`,{
insurancePapers
miningPapers
})
dispatch({
type: ADD_DISPATCH_SUCCESS,
payload: data,
});
}
Backend:
const handler = async (req, res) => {
if (req.method === "POST") {
let reciept = await DispatchReceipt.findOne({
ICDN_No: req.body.ICDN_No,
});
if (reciept) {
return res
.status(409)
.json("Dispatch Receipt With this ICDN Number already exists");
}
if (req.body.differenceInQty) {
req.body.differenceInQty =
req.body.loadedMaterialQty - req.body.unloadedMaterialQty;
} else {
req.body.differenceInQty = 0;
}
//Creating Dispatch Receipt
reciept = await DispatchReceipt.create(req.body);
//Adding receipt ID to customer
const customer = await Customer.findOne({ name: req.body.party });
if (!customer) {
res.status(404).json("Customer Not Found");
}
if (customer) {
customer.dispatchReceipts.push(reciept._id);
customer.save();
}
//response
res.status(200).json(reciept);
} else {
return res.status(500).send("INVALID REQUEST");
}
};
Backend MongoDB Models :
const DispatchReceiptSchema = new mongoose.Schema({
//Other data
//ERROR here \/
insurancePapers: {
public_id: { type: String, required:[true, "Please add public ID"] },
url: { type: String , required:[true, "Please add url"]},
},
//ERROR here \/
miningPapers: {
public_id: {
type: String,
required: [true, "Please Upload Mining Papers"],
},
url: { type: String, required: [true, "Please Upload Mining Papers"] },
},
});
mongoose.models = {};
const DispatchReceipt = mongoose.model(
"DispatchReceipt",
DispatchReceiptSchema
);
export default DispatchReceipt;

Related

Fetching a formData via React Native

I am writing a very dumb application using React Native / Flask but can't seem to be able to construct the formData. The formData.append function gives me this error:Argument of type '{ uri: any; type: string; name: string; }' is not assignable to parameter of type 'string | Blob'. Object literal may only specify known properties, and 'uri' does not exist in type 'Blob'.
This is how I'm fetching, the problem seems to be in the way the formDAta is being created, but I have tried pretty much everything and still doesn't work so I thought of asking here.
const ImagePickerScreen = () => {
const [image, setImage] = useState(null);
const pickImage = async () => {
// No permissions request is necessary for launching the image library
let result = await ImagePicker.launchImageLibraryAsync({
mediaTypes: ImagePicker.MediaTypeOptions.All,
allowsEditing: true,
aspect: [4, 3],
quality: 1,
});
console.log(result);
if (!result.canceled) {
setImage(result.assets[0].uri);
}
};
const handleIsHotdog = async () => {
if (!image) {
alert("No image selected");
return;
}
try {
const formData = new FormData();
formData.append('image', {
uri: image,
type: 'image/jpeg',
name: 'selectedImage.jpg'
});
const response = await fetch('http://my endopoint here', {
method: 'POST',
body: formData,
headers: {
'Content-Type': 'multipart/form-data',
},
});
const responseJson = await response.text();
Alert.alert(
'Result',
responseJson,
[
{ text: 'OK', onPress: () => console.log('OK Pressed') },
],
{ cancelable: false },
);
} catch (error) {
console.error(error);
}
};
And this is on the server-side:
#app.route("/process_image", methods=["POST"])
def classify_image():
image = request.files["image"]
image = PIL.Image.open(image)
# Load the model
model = tf.keras.models.load_model('hotdog_model.h5')
# Preprocess the image
target_size = (224, 224)
image = image.resize(target_size)
image = tf.keras.preprocessing.image.img_to_array(image)
image = np.expand_dims(image, axis=0)
# Use the model to make a prediction
prediction = model.predict(image)
# Return the result
if prediction[0][0] > 0.5:
return "Hotdog"
else:
return "Not Hotdog"
The server works when I do postman request (using formdata.

Missing required parameter - file Cloudinary \Error

first time trying to upload images to Cloudinary and I have come across an issue Missing required parameter- file
In this way I'm Configuring my cloudinary
//Configuring Cloudinary
cloudinary.config({
cloud_name: process.env.ClOUDINARY_NAME,
api_key: process.env.CLOUDINARY_API_KEY ,
api_secret: process.env.CLOUDINARY_API_SECRET,
})
Im using this to add user avatar on cloudinary like this:
//Register user
exports.registerUser = catchAsyncError(async (req, res, next) => {
//avatar img upload
const myCloud = await cloudinary.v2.uploader.upload(req.body.avatar, {
folder: "avatars",
width: 150,
crop: "scale",
});
const { name, email, password } = req.body;
const user = await User.create({
name,
email,
password,
avatar: {
public_id: myCloud.public_id,
url: myCloud.secure_url,
},
});
This is how i am setting the FormData
const registerSubmit = (e) => {
e.preventDefault();
const myForm = new FormData();
myForm.set("name", name);
myForm.set("email", email);
myForm.set("password", password);
myForm.set("avatar", avatar);
dispatch(register(myForm));
};
//For Register
export const register = ({userData}) => async (dispatch) =>{
try{
dispatch({type: REGISTER_USER_REQUEST});
const config = { headers : {"Content-Type": "multipart/form-data"} };
const {data} = await axios.post(
`api/v1/register`,
{userData},
{config}
);
dispatch({type:REGISTER_USER_SUCCESS, payload: data.user});
}
catch(error){
dispatch({type:REGISTER_USER_FAIL, payload:error.response.data.message});
}
but after all this I'm still getting the same error, Please help me

Can't get the data that stored in Redis

I'm trying to create a user after he verified the code that I send him
so first I generate the code in sendCode resolver and save it in Redis using setex
the problem is that code is set in Redis but when I try to use it in createUser resolver using get it returns null.
const sendCode: MutationResolvers["sendCode"] = async ({
input: { phoneNumber, email },
}: {
input: SendCodeInput;
}) => {
const code = generate4digitNum();
await redis.setex(phoneNumber ?? email, THREE_MINS, code);
return {};
};
const createUser: MutationResolvers["createUser"] = async ({
input: { ...userData },
}: {
input: CreateUserInput;
}) => {
const code = await redis.get(userData.phoneNumber ?? userData.email);
if (code !== userData.code) {
throw new Error(errors[0].id);
}
user = await userModel.create({ ...userData});
return {type: user.type, _id: user._id };
};
the redis.ts file that I create:
const client = redis.createClient({
host: process.env.REDIS_HOST,
password: process.env.REDIS_PASSWORD,
port: Number(process.env.REDIS_PORT),
});
client
.on("connect", function () {
console.log(`connected ${client.connected}`);
})
.on("error", function (error) {
console.log(error);
});
export const get: (key: string) => Promise<string> = promisify(client.get).bind(
client
);
export const setex: (
key: string,
seconds: number,
value: string
) => Promise<string> = promisify(client.setex).bind(client);
I will appreciate any kind of help.
Thanks in advance.

Apify - How to Enqueue URL Variations Efficiently

I am creating a new actor in Apify with Cheerio to read an input file of URLs and return primarily two items: (1) the HTTP status code and (2) the HTML title. As part of our process, I would like to be able to try up to 4 variations of each input URL, such as:
HTTP://WWW.SOMEURL.COM
HTTPS://WWW.SOMEURL.COM
HTTP://SOMEURL.COM
HTTPS://SOMEURL.COM
If one of the 4 variations is successful, then the process should ignore the other variations and move to the next input URL.
I read the original input list into a RequestList, and then would like to create the variations in a RequestQueue. Is this the most efficient way to do it? Please see code below, and thank you!
const Apify = require('apify');
const {
utils: { enqueueLinks },
} = Apify;
const urlParse = require('url');
Apify.main(async () => {
const input = await Apify.getInput();
const inputFile = input.inputFile;
console.log('INPUT FILE: ' + inputFile);
const requestList = await Apify.openRequestList('urls', [
{ requestsFromUrl: inputFile, userData: { isFromUrl: true } },
]);
const requestQueue = await Apify.openRequestQueue();
const proxyConfiguration = await Apify.createProxyConfiguration();
const handlePageFunction = async ({ $, request, response }) => {
let parsedHost = urlParse.parse(request.url).host;
let simplifiedHost = parsedHost.replace('www.', '');
const urlPrefixes = ['HTTP://WWW.', 'HTTPS://WWW.', 'HTTP://', 'HTTPS://'];
let i;
for (i = 0; i < urlPrefixes.length; i++) {
let newUrl = urlPrefixes[i] + simplifiedHost;
console.log('NEW URL: ' + newUrl);
await requestQueue.addRequest({ url: newUrl });
}
console.log(`Processing ${request.url}`);
const results = {
inputUrl: request.url,
httpCode: response.statusCode,
title: $('title').first().text().trim(),
responseUrl: response.url
};
await Apify.pushData(results);
};
const crawler = new Apify.CheerioCrawler({
proxyConfiguration,
maxRequestRetries: 0,
handlePageTimeoutSecs: 60,
requestTimeoutSecs: 60,
requestList,
requestQueue,
handlePageFunction,
handleFailedRequestFunction: async ({ request }) => {
await Apify.pushData({ inputUrl: request.url, httpCode: '000', title: '', responseUrl: ''});
}
});
await crawler.run();
});
you should create your URL list beforehand. the handlePageFunction is only used for the actual scraping part, and you should only have the Apify.pushData there:
//...
const initRequestList = await Apify.openRequestList('urls', [
{ requestsFromUrl: inputFile },
]);
const parsedRequests = [];
let req;
while (req = await initRequestList.fetchNextRequest()) {
const parsedHost = urlParse.parse(req .url).host;
const simplifiedHost = parsedHost.replace('www.', '');
const urlPrefixes = ['HTTP://WWW.', 'HTTPS://WWW.', 'HTTP://', 'HTTPS://'];
for (let i = 0; i < urlPrefixes.length; i++) {
let newUrl = urlPrefixes[i] + simplifiedHost;
console.log('NEW URL: ' + newUrl);
parsedRequests.push({
url: newUrl,
userData: { isFromUrl: true }
});
}
}
const requestList = await Apify.openRequestList('starturls', parsedRequests);
//...
const crawler = new Apify.CheerioCrawler({
proxyConfiguration,
maxRequestRetries: 0,
handlePageTimeoutSecs: 60,
requestTimeoutSecs: 60,
handlePageFunction,
requestList,
handleFailedRequestFunction: async ({ request }) => {
await Apify.pushData({ inputUrl: request.url, httpCode: '000', title: '', responseUrl: ''});
}
});
//...
requestsFromUrl is a greedy function that tries to parse all URLs from to the given resource. so you'll have to perform the processing as an additional step.

While loop is not generating data randomly

I'm creating API tests with async-await using Supertest and Mocha.
In the accountsData.js file I created a function to generate random test accounts.
In the accountsHelper.js file I created a function to create unlimited accounts using a while loop
When I run tests on the post_accounts.js file, the first account is created successfully, but from the second account, the data generated in the accountsData.js file is already repeated.
Why isn't data randomly generated when I create more than one account using data from the accountsData.js file?
accountsData.js
const casual = require('casual');
function randomAccount() {
return {
'email': casual.email,
'password': '123456',
};
}
module.exports = {
randomAccount,
};
accountsHelper.js
const request = require('supertest');
const commonData = require('../data/commonData');
/* eslint-disable no-console */
const accountList = [];
let counterAccounts;
module.exports = {
async createAccount(account, accountsToCreate = 2, validateResponse = true) {
counterAccounts = 0;
while (counterAccounts < accountsToCreate) {
try {
const res = await request(commonData.environment.staging)
.post(commonData.endpoint.accounts)
.send(account);
if (validateResponse === true) {
if (res.status === commonData.statusCode.ok) {
accountList.push(res.body);
} else {
throw new Error('Email already exists\n\n' + JSON.stringify(res.body, null, ' '));
}
} else {
return res.body;
}
} catch (err) {
console.log(err);
}
counterAccounts++;
}
return accountList;
},
};
post_accounts.js
const accountsData = require('../../data/accountsData');
const accountsHelper = require('../../helpers/accountsHelper');
const account = accountsData.randomAccount();
describe('Create accounts with email and password', () => {
context('valid accounts', () => {
it('should create an account successfully', async() => {
const res = await accountsHelper.createAccount(account);
// eslint-disable-next-line no-console
console.log(res);
});
});
});
API response:
Create accounts with email and password
valid accounts
Error: Email already exists
{
"error": {
"statusCode": 422,
"name": "ValidationError",
"message": "The `account` instance is not valid. Details: `email` Email already exists (value: \"Lemuel.Lynch#Susan.net\").",
"details": {
"context": "account",
"codes": {
"email": [
"uniqueness"
]
},
"messages": {
"email": [
"Email already exists"
]
}
}
}
}
at Object.createAccount (/Users/rafael/Desktop/projects/services/test/helpers/accountsHelper.js:24:19)
at process._tickCallback (internal/process/next_tick.js:68:7)
[ { 'privacy-terms': false,
'created-date': '2019-08-24T10:00:34.094Z',
admin: false,
isQueued: false,
lastReleaseAttempt: '1970-01-01T00:00:00.000Z',
'agreed-to-rules': { agreed: false },
email: 'Lemuel.Lynch#Susan.net',
id: '5d610ac213c07d752ae53d91' } ]
✓ should create an account successfully (2243ms)
1 passing (2s)
The code that you posted doesn't correspond to the code that you're describing in prose.
However, I tested your accountsData.js file, in the way that your words (but not your code) say that you're using it, and it works fine.
// main.js
const { createPerson } = require(__dirname + '/accountsData')
console.log(createPerson())
console.log(createPerson())
console.log(createPerson())
console.log(createPerson())
console.log(createPerson())
Output from running it once:
$ node main.js
{ email: 'Anne_Ebert#Macie.com', password: '123456' }
{ email: 'Manley.Lindgren#Kshlerin.info', password: '123456' }
{ email: 'McClure_Thurman#Zboncak.net', password: '123456' }
{ email: 'Breitenberg.Alexander#Savannah.com', password: '123456' }
{ email: 'Keely.Mann#Stark.io', password: '123456' }
And again:
$ node main.js
{ email: 'Destany_Herman#Penelope.net', password: '123456' }
{ email: 'Narciso_Roob#gmail.com', password: '123456' }
{ email: 'Burnice_Rice#yahoo.com', password: '123456' }
{ email: 'Roma_Nolan#yahoo.com', password: '123456' }
{ email: 'Lilla_Beier#yahoo.com', password: '123456' }
Nothing in the code that you posted is actually requiring or using accountsData.js. If you change your code to use it, I think you'll see, like I do, that it works.
Problem is, you are generating the random account and storing it in a variable 'post_accounts.js(line 3)'. So, when you create an account, you are using the same payload to create multiple accounts, which obviously throws an error.
I just modified the accountHelper to properly handle your scenario. Hope this helps.
Note: The code is not tested, I just wrote it from my mind. Please test and let me know if it works.
// accountsHelper.js
const request = require('supertest');
const commonData = require('../data/commonData');
const accountsData = require('../../data/accountsData');
/* eslint-disable no-console */
const accountList = [];
module.exports = {
async createAccount(account, accountsToCreate = 1, validateResponse = true) {
// creates an array of length passed in accountsToCreate param
return (await Promise.all(Array(accountsToCreate)
.fill()
.map(async () => {
try {
const res = await request(commonData.environment.staging)
.post(commonData.endpoint.accounts)
// takes account if passed or generates a random account
.send(account || accountsData.randomAccount());
// validates and throw error if validateResponse is true
if (validateResponse === true && (res.status !== commonData.statusCode.ok)) {
throw new Error(
'Email already exists\n\n' +
JSON.stringify(res.body, null, ' ')
);
}
// return response body by default
return res.body;
} catch (e) {
console.error(e);
// return null if the create account service errors out, just to make sure the all other create account call doesnt fail
return null;
}
})))
// filter out the null(error) responses
.filter(acc => acc);
}
};
//post_accounts.js
const accountsHelper = require('../../helpers/accountsHelper');
const accountsData = require('../../data/accountsData');
const GENERATE_RANDOM_ACCOUNT = null;
describe('Create accounts with email and password', () => {
context('valid accounts', () => {
it('should create an account successfully', async () => {
const result = await accountsHelper.createAccount();
expect(result.length).toEquals(1);
});
it('should create 2 accounts successfully', async () => {
const result = await accountsHelper.createAccount(GENERATE_RANDOM_ACCOUNT, 2);
expect(result.length).toEquals(2);
});
it('should not create duplicate accounts', async () => {
const account = accountsData.randomAccount();
// here we are trying to create same account twice
const result = await accountsHelper.createAccount(account, 2);
// expected result should be one as the second attempt will fail with duplicate account
expect(result.length).toEquals(1);
});
});
});

Categories