RN-fetch-blob not downloading file always failed - react-native

Im working on react native fetch blob to download the file. The file basically are in my nodejs server.
I have tried to get it from post man and its successfully working. But when i attached the api into rn-fetch-blob it shows me download failed even file exists. I have checked 10 time my installation is correct there is no issue there. Can any body help me to get out of this.
SO this is my node api router.post('/download-proof', documents.proofDownload);
proofDownload: (req, res)=> {
let filepath = path.join(__dirname,'../../../documents/')+req.body.filename
res.setHeader('Content-Disposition', 'attachment; filename=' + req.body.filename);
res.setHeader('Content-Transfer-Encoding', 'binary');
res.setHeader('Content-Type', req.body.mimetype);
res.download(filepath)
},
its working fine in postman
This one is rn-fetch-blob
let options = {
fileCache: true,
appendExt: getExt,
addAndroidDownloads: {
useDownloadManager: true, // setting it to true will use the device's native download manager and will be shown in the notification bar.
notification: true,
description: 'Downloading file.',
path:
pathToDir +
`/${file.filename}` ,
},
path:
pathToDir +
`/${file.filename}` ,
notification: true,
};
console.log(file," docs")
console.log(options.path, pathToDir,"options")
let body = {
filename: file.filename,
mimetype: file.mimetype
}
console.log(body, "line no 62")
let url = `http://3.21.33.146:3000/download-proof`;
console.log(url);
config(options)
.fetch("POST", url,{}, JSON.stringify(body))
.progress({interval: 250}, (received, total) => {})
.then((res) => {
console.log(res, "fetch blob response")
}).catch((err) => {
console.log(err)
})
} else {
Alert.alert(
"Permission Denied!",
"You need to give storage permission to download the file"
);
}
} catch (err) {
console.log(err);
}
}
It gives me status code 16 error don't know what the problem is.

Related

Multer google storage returns 'Internal Server Error'

I have just switched image upload with Multer from local to Google Cloud Storage using 'multer-google-storage'. It used to work fine earlier, but now sends a 500 Internal Server Error without message. I am using Nodejs and Express, React for front end. FormData is formatted correctly since it works fine if I go back to local storage. Any ideas on how to fix this? Or display an error message? I am not able to find much documentation on 'multer-google-storage'. Thanks for the help!
Here the back-end post route (I hid the configuration options)
const multer = require('multer');
const multerGoogleStorage = require('multer-google-storage');
const upload = multer({
storage: multerGoogleStorage.storageEngine({
autoRetry: true,
bucket: '******',
projectId: '******',
keyFilename: '../server/config/key.json',
filename: (req, file, callback) => {
callback(null, file.originalname);
},
}),
});
//#route POST api/listings
//#description Create listing
//#access Private
router.post(
'/',
upload.any(),
[
isLoggedIn,
[
check('title', 'Title is required').not().isEmpty(),
check('coordinates').not().isEmpty(),
check('address').not().isEmpty(),
check('price', 'Set a price').not().isEmpty(),
check('description', 'Type a description').not().isEmpty(),
check('condition', 'Declare the condition').not().isEmpty(),
check('category', 'Please select a category').not().isEmpty(),
],
],
async (req, res) => {
const errors = validationResult(req);
if (!errors.isEmpty()) {
console.log('validation error');
return res.status(400).json({ errors: errors.array() });
}
try {
const files = req.files;
let images = [];
for (let image of files) {
images.push(image.originalname);
}
const newListing = new Listing({
title: req.body.title,
images: images,
coordinates: JSON.parse(req.body.coordinates),
price: req.body.price,
description: req.body.description,
condition: req.body.condition,
dimensions: req.body.dimensions,
quantity: req.body.quantity,
address: req.body.address,
author: req.user.id,
category: JSON.parse(req.body.category),
});
const author = await User.findById(req.user.id);
await author.listings.push(newListing);
await author.save();
const listing = await newListing.save();
res.json(listing);
} catch (error) {
console.log('error');
console.error(error);
res.json(error);
res.status(500).send('Server Error');
}
}
);
I have solved the issue, it was a permission problem. My previous Google Cloud Storage bucket had access control 'Uniform' while it should have been 'Fine-grained'.

How to upload image with express-fileupload from CKEditor5 properly?

My api as follows
router.post("/upload", async (req, res) => {
if (!req.files || Object.keys(req.files).length === 0) {
return res.status(400).send("No files were uploaded.");
}
console.log(req.files)
let file = req.files.upload;
let uploadPath = __dirname + "/../public/" + file.name;
file.mv(uploadPath, function (err) {
if (err) {
console.log(err)
return res.status(500).send(err)
}
res.sendStatus(200);
});
});
My react component
<CKEditor
editor={ClassicEditor}
config={{
ckfinder: {
uploadUrl: "/api/upload",
},
}}
data={props.state.tech.assess_info}
onChange={(event, editor) => {
..
}}
/>
Currently when I upload image from CKeditor, image is successfully uploaded(written to "public/{filename}" on server side). However CKEditor error popups and stating "cannot upload". I believe CKeditor is expecting specific response code, not just HTTP status 200. What do you guys think?
Ckeditor is expecting following response from API.
res.status(200).json({
uploaded: true,
url: `/uploads/${file.name}`,
});
Whole api code if anyone needs.
// Upload a file
router.post("/upload", async (req, res) => {
if (!req.files || Object.keys(req.files).length === 0) {
return res.status(400).send("No files were uploaded.");
}
let file = req.files.upload;
let uploadPath = __dirname + "/../public/uploads/" + file.name;
file.mv(uploadPath, function (err) {
if (err) return res.status(500).send(err);
res.status(200).json({
uploaded: true,
url: `/uploads/${file.name}`,
});
});
});

Cloudinary\Error: Missing required parameter - file - Express and Postman

first time trying to upload images to Cloudinary and I have come across an issue when using Express via Postman.
Using form-data on setting 'file' to upload an image to Cloudinary
As of now, when I try to access the req.body I get an empty object, so I guess that has to do with why cloudinary.uploader.upload cannot read the file passed as its first param, since its req.body.file, as shown in the code below.
cloudinary.config({
cloud_name: process.env.CLOUDINARY_CLOUD_NAME,
api_key: process.env.CLOUDINARY_KEY,
api_secret: process.env.CLOUDINARY_SECRET
})
exports.upload = async (req, res) => {
try{
console.log(req.body);
const result = await cloudinary.uploader.upload(req.body.file, {
public_id: `${Date.now()}`,
resource_type: "auto"
})
return res.json({
public_id: result.public_id,
url: result.secure_url
})
}catch(err){
console.log(err)
}
}
The error message I get:
{
message: 'Missing required parameter - file',
name: 'Error',
http_code: 400
}
Any suggestions to solve this issue?
I solved it! I was not able to pass the form-data as req.body to the server, so I had to try and access it through req.files, but was not able to with that either, so I searched a bit and found a middleware 'express-fileupload', and that did the trick. I just added it in my app.js and used
const fileupload = require('express-fileupload');
app.use(fileupload({useTempFiles: true}))
So now I can access my req.files.
exports.upload = async (req, res) => {
const file = req.files.image
try{
console.log(file);
const result = await cloudinary.uploader.upload(file.tempFilePath, {
public_id: `${Date.now()}`,
resource_type: "auto"
})
res.json({
public_id: result.public_id,
url: result.secure_url
})
}catch(err){
console.log("Error", err)
return res.status(400).json({error: err})
}
}
The response I get is:
{
name: 'some-image.png',
data: <Buffer >,
size: 99770,
encoding: '7bit',
tempFilePath: ' **C:\\filepath\some-image.png** ',
truncated: false,
mimetype: 'image/png',
md5: 'b5f612a571442bf604952fd12c47c1bf',
mv: [Function: mv]
}
POST /cloudinary/upload-images 200 1617.944 ms - 119
And it is uploaded successfully to my Cloudinary.
const result = await cloudinary.uploader.upload(req.file, {
public_id: ${Date.now()},
resource_type: "auto"
})
and add file from form data and type should be File
Solved!
This is how i am setting the FormData
let myTestForm = new FormData();
myTestForm.set("name", name);
myTestForm.set("email", email);
myTestForm.set("Avatar", Avatar);
myTestForm.set("password", password);
This is how i am using the FormData
const config = {
headers: {
"Content-type": "multipart/form-data",
},
};
const { data } = await axios.post(`/api/v1/register`, userData, { config });
please don't pass it this way { userData} , had struggled for with this :/
This is how i am uploading image
const myCloud = await cloudinary.v2.uploader.upload(req.body.Avatar, {
folder: "Avatars",
width: 150,
crop: "scale",
public_id: `${Date.now()}`,
resource_type: "auto",
});
PS : in my case i had to upload only 1 image. Have not passed any parameter in app.js file
app.use(bodyParser.urlencoded({ extended: true }));
app.use(fileUpload());

Show downloading file success on notification and open file using rn-fetch-blob

I am new on react native. I am getting blob response and try to save as pdf in storage using rn-fetch-blob. Using my code file saved into file storage but unable to show downloading notification.
Here is my code:
var date = new Date();
var path = RNFetchBlob.fs.dirs.DownloadDir + '/Inspection_' +Math.floor(date.getTime() + date.getSeconds() / 2)+'.pdf';
RNFetchBlob
.config({
// addAndroidDownloads : {
// useDownloadManager : true,
// title : 'Inspections_'+inspectionId,
// description : 'File successfully downloaded',
// // path:path,
// // mime : 'application/pdf',
// // mediaScannable : true,
// notification : true,
// }
})
.fetch('POST', url+'customer/create-pdf?id='+inspectionId, {
Accesstoken: 'Bearer '+this.token
})
.then((res) => {
console.log(res);
let base64Str = res.data;
// let pdfLocation = RNFetchBlob.fs.dirs.DownloadDir + '/Inspection_' +this.state.inspectionId+'.pdf';
RNFetchBlob.fs.writeFile(path, base64Str, 'base64');
// RNFetchBlob.android.actionViewIntent(path, 'application/pdf')
})
.catch((errorMessage, statusCode) => {
console.log(errorMessage);
console.log(statusCode);
})
How to set config to show notification.
You can use promise and Alert which will be triggered on downloading like this
RNFS.downloadFile({
fromUrl: newUrl,
background: true,
toFile: `${RNFS.DocumentDirectoryPath}/${fileName}`,
}).promise.then(async res => {
this.setState({
progress: 100,
loading: false,
downloaded: true,
popupMessage: "File downloaded successfully."
});
}).catch(err => {
this.setState({
loading: false
})
});
on downloaded flag you can show the alert or custom popup

How to download a file (image,gif,etc..) in react native

I have tried this code but my app is crashing without showing any error , i couldnt figure out what is the error
const {config,fs} = RNFetchBlob;
const { params } = this.props.navigation.state;
let PictureDir = fs.dirs.PictureDir // this is the pictures directory. You can check the available directories in the wiki.
let options = {
fileCache: true,
addAndroidDownloads : {
useDownloadManager : false, // setting it to true will use the device's native download manager and will be shown in the notification bar.
notification : false,
path: PictureDir + "/me_image", // this is the path where your downloaded file will live in
}
}
config(options).fetch('GET',url).then((res) => {
alert('Done');
})
saveToCameraRoll = () => {
const{selectedImage, downlaodUrl} = this.state
let url = downlaodUrl[0].url;
ToastAndroid.show("Image is Saving...", ToastAndroid.SHORT)
if (Platform.OS === 'android'){
RNFetchBlob
.config({
fileCache : true,
appendExt : 'jpg'
})
.fetch('GET', url)
.then((res) => {
console.log()
CameraRoll.saveToCameraRoll(res.path())
.then((res) => {
console.log("save", res)
ToastAndroid.show("Image saved Successfully.", ToastAndroid.SHORT)
}).catch((error) => {
ToastAndroid.show("Ops! Operation Failed", ToastAndroid.SHORT)
})
})
} else {
CameraRoll.saveToCameraRoll(url)
.then(alert('Success', 'Photo added to camera roll!'))
ToastAndroid.show("Image saved Successfully.", ToastAndroid.SHORT)
}
}