How to send file received through api to google drive nodejs - javascript

I am new to Nodejs and trying to send file received through multer to google drive. However I am setting
var media = {
mimeType: req.file.mimetype,
body:req.file
};
Which is giving me error as
const index = require('../index.js');
const { google } = require('googleapis');
let drive = google.drive('v3');
const receive = multer();
router.post("/insertNewProduct", auth, receive.single('productUrl'), async (req, res) => {
try {
const data = req.body;
var folderId = '1v3tdYH_GLtCOOxhQ8HXDdRAb-2Jh455_';
let fs = require('fs')
var fileMetadata = {
'name': new Date().toISOString()+req.file.filename,
parents: [folderId]
};
var media = {
mimeType: req.file.mimetype,
body:req.file
};
drive.files.create({
auth: index.jwtClient,
resource: fileMetadata,
publishAuto: true,
media: media,
fields: 'id'
},
async function (err, file) {
if (err) {
// Handle error
console.error(err);
}
else {
console.log('********File create success. File Id: ', file.data.id);
res.status(201).send({
message: "Record Create Successfully",
data: newRows
});
}
}
);
}
}
} catch (e) {
console.log("Inside catch: " + e);
res.status(404).send({
message: e,
data: {}
});
}
});
As I understand the error, how I set the body:req.file is wrong.
Here's how req.file look like.
How can I pass req.file to
var media = {
mimeType: req.file.mimetype,
body:req.file
};
I tried body:req.file.buffer but it didn't work.

Related

MERN - Getting error: "Cannot read property 'path' of undefined" when trying to upload a pdf file using multer

Like I said on the title, I'm facing that error when I'm trying to upload a file from the client-side. Here are the code blocks for more context:
Route:
const express = require("express");
const { upload } = require("../middlewares/uploadMiddleware");
const { registerResearchSheet } = require("../controllers/researchSheetControllers");
const router = express.Router();
router.route("/").post(upload.single("file"), registerResearchSheet);
Middleware:
const multer = require("multer");
const storage = multer.diskStorage({
destination: function (req, file, cb) {
cb(null, "backend/uploads/");
},
filename: function (req, file, cb) {
cb(
null,
new Date().toISOString().replace(/:/g, "-") + "-" + file.originalname
);
},
});
const fileFilter = (req, file, cb) => {
if (file.mimetype === "application/pdf") {
cb(null, true);
} else {
cb(null, false);
}
};
const upload = multer({ storage: storage, fileFilter: fileFilter });
module.exports = { upload };
Controller:
const asyncHandler = require("express-async-handler");
const ResearchSheet = require("../models/researchSheetModel");
const registerResearchSheet = asyncHandler(async (req, res) => {
const {
title,
director,
coordinator,
students,
reviewers,
proposalType,
investigationType,
status,
} = req.body;
if (!req.file) {
res.status(400);
throw new Error("The file hasn't be uploaded correctly"); **//This is the triggering error**
}
const file = req.file.path;
const researchSheetExists = await ResearchSheet.findOne({ title, students });
if (researchSheetExists) {
res.status(400);
throw new Error("Title or students can't be repeated");
}
const researchSheet = await ResearchSheet.create({
title,
file, // file: buffer,
director,
coordinator,
students,
reviewers,
proposalType,
investigationType,
status,
});
if (researchSheet) {
res.status(201).json({
_id: researchSheet._id,
title: researchSheet.title,
file: researchSheet.file,
director: researchSheet.director,
coordinator: researchSheet.coordinator,
students: researchSheet.students,
reviewers: researchSheet.reviewers,
proposalType: researchSheet.proposalType,
investigationType: researchSheet.investigationType,
status: researchSheet.status,
});
} else {
res.status(400);
throw new Error("An error has ocurred");
}
});
And finally the frontend part:
const [file, setFile] = useState(null);
//code..
const singleFileUpload = (e) => {
setFile(e.target.files[0]);
};
const submitHandler = async (e) => {
e.preventDefault();
const formData = new FormData();
formData.append("title", title);
formData.append("file", file);
formData.append("director", director);
formData.append("coordinator", coordinator);
formData.append("students", students);
formData.append("proposalType", proposalType);
formData.append("investigationType", investigationType);
console.log(file); //This log is correctly showing the File and its properties
if (
!title ||
!coordinator ||
!students ||
!proposalType ||
!investigationType
) {
setMessage("You must fill all the fields");
} else {
dispatch(registerResearchSheetAction(formData));
// history.push("/listresearchsheets");
}
};
//more code...
<Form.Control
className="mb-3"
type="file"
accept=".pdf"
onChange={(e) => singleFileUpload(e)}
/>
<Button type="submit">Register</Button>
Action:
export const registerResearchSheetAction =
(
title,
file,
director,
coordinator,
students,
reviewers,
proposalType,
investigationType,
status
) =>
async (dispatch) => {
try {
dispatch({
type: RESEARCHSHEET_REGISTER_REQUEST,
});
const formData = new FormData();
formData.append("file", file);
formData.append("title", title);
formData.append("director", director);
formData.append("coordinator", coordinator);
formData.append("students", students);
formData.append("reviewers", reviewers);
formData.append("proposalType", proposalType);
formData.append("investigationType", investigationType);
formData.append("status", status);
const config = {
headers: {
"Content-Type": "multipart/form-data",
},
};
const { data } = await axios.post(
"/api/researchsheets",
formData,
config
);
dispatch({ type: RESEARCHSHEET_REGISTER_SUCCESS, payload: data });
} catch (error) {
dispatch({
type: RESEARCHSHEET_REGISTER_FAIL,
payload:
error.response && error.response.data.message
? error.response.data.message
: error.message,
});
}
};
I already tested the functionality on the server-side using Postman and it is uploading, more than the file, the route/path of it successfully on the database. That's why I'm thinking that the problem must be on the client-side. I really don't know what I'm missing here, so that's why I came for a little of help, I hope I was clear on my explanaiton.
Thank you in advance!

TypeError: storageRef.getDownloadURL is not a function

exports.add = async (req, res) => {
const { body } = req;
var storageRef = fb.firebaseAdmin
.storage()
.bucket(
"gs://test-ptoject-2147f.appspot.com); var filename='computer.jpg'; var path='./computer.jpg'"
);
try {
if (filename == undefined) {
return res.status(400).send({ message: 'Please upload a file!' });
}
const storage = await storageRef.upload(path, {
public: true,
destination: `/uploads/${filename}`,
metadata: {
firebaseStorageDownloadTokens: uuidv4(),
},
});
res.status(200).send({ message: 'File uploaded successfully.!' });
storageRef.getDownloadURL().then(function (url) {
const image = doc('computer');
image.src = url;
console.log('your url is:', url);
});
} catch (err) {
console.log(err);
}
};
With the Admin SDK, with the following code
var storageRef = fb.firebaseAdmin
.storage()
.bucket(...);
you actually define a Bucket and there isn't any getDownloadURL() method for a Bucket.
You should call the getSignedUrl() method on a File. The getDownloadURL() method is only for the JavaScript SDK.
The following should do the trick (untested):
const storage = await storageRef.upload(path, {
public: true,
destination: `/uploads/${filename}`,
metadata: {
firebaseStorageDownloadTokens: uuidv4(),
},
});
const signedUrlResponse = await storageRef.getSignedUrl();
const url = await signedUrlResponse[0];
Note that it seems there is a typo/problem in this part of your code, with the value you pass to the bucket() method:
var storageRef = fb.firebaseAdmin
.storage()
.bucket(
"gs://test-ptoject-2147f.appspot.com); var filename='computer.jpg'; var path='./computer.jpg'"
);

S3 Upload Failing Silently in Production

I'm struggling to debug a NextJS API that is working in development (via localhost) but is silently failing in production.
Below, the two console.log statements are not returning, so I suspect that the textToSpeech call is not executing correctly, potentially in time?
I'm not sure how to rectify, happy to debug as directed to resolve this!
const faunadb = require('faunadb')
const secret = process.env.FAUNADB_SECRET_KEY
const q = faunadb.query
const client = new faunadb.Client({ secret })
const TextToSpeechV1 = require('ibm-watson/text-to-speech/v1')
const { IamAuthenticator } = require('ibm-watson/auth')
const AWS = require('aws-sdk')
const { randomUUID } = require('crypto')
import { requireAuth } from '#clerk/nextjs/api'
module.exports = requireAuth(async (req, res) => {
try {
const s3 = new AWS.S3({
accessKeyId: process.env.AWS_ACCESS_KEY,
secretAccessKey: process.env.AWS_SECRET_ACCESS_KEY
})
const textToSpeech = new TextToSpeechV1({
authenticator: new IamAuthenticator({
apikey: process.env.IBM_API_KEY
}),
serviceUrl: process.env.IBM_SERVICE_URL
})
const uuid = randomUUID()
const { echoTitle, chapterTitle, chapterText } = req.body
const synthesizeParams = {
text: chapterText,
accept: 'audio/mp3',
voice: 'en-US_KevinV3Voice'
}
textToSpeech
.synthesize(synthesizeParams)
.then(buffer => {
const s3Params = {
Bucket: 'waveforms/audioform',
Key: `${uuid}.mp3`,
Body: buffer.result,
ContentType: 'audio/mp3',
ACL: 'public-read'
}
console.log(buffer.result)
console.log(s3Params)
s3.upload(s3Params, function (s3Err, data) {
if (s3Err) throw s3Err
console.log(`File uploaded successfully at ${data.Location}`)
})
})
.catch(err => {
console.log('error:', err)
})
const dbs = await client.query(
q.Create(q.Collection('audioform'), {
data: {
title: echoTitle,
published: 2022,
leadAuthor: 'winter',
user: req.session.userId,
authors: 1,
playTime: 83,
chapters: 1,
gpt3Description: '',
likes: 20,
image:
'https://waveforms.s3.us-east-2.amazonaws.com/images/Mars.jpeg',
trackURL: `https://waveforms.s3.us-east-2.amazonaws.com/audioform/${uuid}.mp3`,
albumTracks: [
{
title: chapterTitle,
text: chapterText,
trackURL: `https://waveforms.s3.us-east-2.amazonaws.com/audioform/${uuid}.mp3`
}
]
}
})
)
res.status(200).json(dbs.data)
} catch (e) {
res.status(500).json({ error: e.message })
}
})
Replace the async fragments something like this, assuming they are meant to be executed sequentially.
try {
// code removed here for clarity
const buffer = await textToSpeech.synthesize(synthesizeParams);
const s3Params = {
Bucket: 'waveforms/audioform',
Key: `${uuid}.mp3`,
Body: buffer.result,
ContentType: 'audio/mp3',
ACL: 'public-read'
}
await s3.upload(s3Params).promise();
const dbs = await client.query(...);
res.status(200).json(dbs.data);
} catch (e) {
res.status(500).json({ error: e.message });
}

How can I send image to backend in react native?

I want to use a library called react-native-image-picker to deliver the image to the backend server using formData and save it to the computer diskStorage upload using multer.
However, there is some confusion in using this. If I use my code I get this error:
MulterError: Unexpected fielderror.
How can I fix the code?
this is my code
(front/Third.js)
const Third = () => {
const [imageSource, setImageSource] = useState(undefined);
const dispatch = useDispatch();
const options = {
title: 'Load Photo',
customButtons: [
{name: 'button_id_1', title: 'CustomButton 1'},
{name: 'button_id_2', title: 'CustomButton 2'},
],
storageOptions: {
skipBackup: true,
path: 'images',
},
};
const showCameraRoll = () => {
launchImageLibrary(options, (response) => {
if (response.error) {
console.log('LaunchImageLibrary Error: ', response.error);
} else {
setImageSource(response.uri);
}
console.log('response.uri:', response.uri);
// response.uri: file:///data/user/0/com.cookingrn/cache/rn_image_picker_lib_temp_5f6898ee-a8d4-48c9-b265-142efb11ec3f.jpg
const form = new FormData();
form.append('Files', {
name: 'SampleFile.jpg', // Whatever your filename is
uri: response.uri, // file:///data/user/0/com.cookingrn/cache/rn_image_picker_lib_temp_5f6898ee-a8d4-48c9-b265-142efb11ec3f.jpg
type: 'image/jpg', // video/mp4 for videos..or image/png etc...
});
dispatch({
type: UPLOAD_IMAGES_REQUEST,
data: form,
});
});
};
return (
<Container>
{imageSource && <Photo source={{uri: imageSource}} />}
<ImagePickerButton onPress={showCameraRoll}>
<Label>Show Camera Roll</Label>
</ImagePickerButton>
</Container>
);
};
export default Third;
(backend/post.js)
try {
fs.accessSync('uploads');
} catch (error) {
console.log('uploads 폴더가 없으므로 생성합니다.');
fs.mkdirSync('uploads');
}
const upload = multer({
storage: multer.diskStorage({
destination(req, file, done) {
done(null, 'uploads');
},
filename(req, file, done) {
const ext = path.extname(file.originalname);
const basename = path.basename(file.originalname, ext);
done(null, basename + '_' + new Date().getTime() + ext);
},
}),
limits: {fileSize: 20 * 1024 * 1024},
});
router.post('/images', isLoggedIn, upload.array('image'), (req, res, next) => {
// dispatch UPLOAD_IMAGES_REQUEST POST /post/images
res.json(req.files.map((v) => v.filename));
});
(saga/index.js)
function uploadImagesAPI(data) {
return axios.post('/post/images', data);
}
function* uploadImages(action) {
try {
const result = yield call(uploadImagesAPI, action.data);
yield put({
type: UPLOAD_IMAGES_SUCCESS,
data: result.data,
});
} catch (err) {
console.error(err);
yield put({
type: UPLOAD_IMAGES_FAILURE,
error: err.response.data,
});
}
}
Create a FormData and send a post request to backend by including that form in the body of the request
const SendFileToBackend = (uri) => {
const form = new FormData();
form.append("Files", {
name: "SampleFile.jpg", // Whatever your filename is
uri: uri, // file:///data/user/0/com.cookingrn/cache/rn_image_picker_lib_temp_5f6898ee-a8d4-48c9-b265-142efb11ec3f.jpg
type: "image/jpg", // video/mp4 for videos..or image/png etc...
});
// Perform a Post request to backend server by putting `form` in the Body of the request
};

Upload Image from React Native to MongoDB Atlas using Nodejs Express Multer

I am trying to upload a profile image of a user from React Native App(Android). I am new to uploading image so I searched and found a package called multer. As I am using Mongodb Atlas, multer has a storage option of MemoryStorage and using MemoryStorage I tried uploading the image to Atlas.But the problem I am facing is that I dont the format in which I have to send the data to Nodejs. I use FormData() to send the image details to Nodejs.I may be wrong in choosing the format or package or anywhere.Please correct me if find me wrong anywhere.Below is code for everything.
avatar.js
const avatarSchema = new Schema(
{
profile_avatar: {
type: Buffer,
contentType: String,
// required: [true, 'fee is required'],
},
},
{
timestamps: true,
},
);
const avatar = mongoose.model('avatar', avatarSchema);
module.exports = avatar;
avatar route
let Avatar = require('../models/avatar');
const multer = require('multer');
var storage = multer.memoryStorage();
var upload = multer({storage: storage});
router.route('/add/image').post(upload.single('avatar'), (req, res, next) => {
console.log(req); // it does not get hit
var newAvatar = new Avatar();
newAvatar.profile_avatar = req.file.buffer;
newAvatar.save(function(err) {
console.log('error', err);
if (err) {
console.log(error);
} else {
res.send({message: 'uploaded successfully'});
}
});
});
React Native Code
//Function to select single image from gallery(its working fine)
imagePick = () => {
let options = {
quality: 0.2,
maxWidth: 500,
maxHeight: 500,
allowsEditing: true,
noData: true,
storageOptions: {
skipBackup: false,
path: 'images',
},
};
ImagePicker.launchImageLibrary(options, response => {
console.log('Response = ', response);
if (response.didCancel) {
console.log('User cancelled image picker');
} else if (response.error) {
console.log('ImagePicker Error: ', response.error);
} else if (response.customButton) {
console.log('User tapped custom button: ', response.customButton);
alert(response.customButton);
} else {
this.setState({
imageData: response,
});
}
});
};
//Function to structure FormData
createFormData = photo => {
const data = new FormData();
data.append('avatar', {
name: photo.fileName,
type: photo.type,
uri:
Platform.OS === 'android'
? photo.uri
: photo.uri.replace('file://', ''),
};);
return data;
};
//Function to send Image data to Nodejs(Not Working)
sendImage = () => {
fetch('http://10.0.2.2:5000/user/add/image', {
method: 'POST',
credentials: 'same-origin',
redirect: 'follow',
referrer: 'no-referrer',
body: this.createFormData(this.state.imageData),
})
.then(response => response.json())
.then(response => {
console.log('upload succes', response);
Alert.alert('Upload success!');
})
.catch(error => {
console.log('upload error', error);
Alert.alert('Upload failed!');
});
};
Any other way I can upload the image? Any help would be appreciated.

Categories

Resources