Displaying pdf file using react-pdf from external source with NextJs - pdf

Hi i was using NextJs and trying to display pdf file within the web, i was using react-pdf for the package. When using
<Document
file={"http://example.com/sample.pdf"}
onSourceError={(err) => console.log('source err', err)}
onLoadError={err => console.log('load err', err)}
>
<Page
pageNumber={pageNumber}
width={width}
/>
i was having a CORS problem, so i was trying to solve it using NextJs API Routes
api/pdf.js
const request = require('request');
export default (req, res) => {
return new Promise(resolve => {
res.statusCode = 200
res.setHeader('Content-Length', 99999);
res.setHeader('Content-Type', 'application/pdf')
res.setHeader('Content-Disposition', 'attachment; filename=quote.pdf');
let { parentid } = req.headers;
switch (true) {
case req.method === 'GET':
console.log('GET')
request.get('http://example.com/sample.pdf', {}, function (err, response, body) {
if (err) {
console.log('err', err)
res.status(500).json({ code: 'Internal Server Error' })
resolve();
} else {
res.status(200).send(body)
resolve()
}
})
break;
default:
res.status(400).json({ code: 'MethodNotAllowed' })
break;
}
})
}
I tried it in insomnia and i do get a pdf response, but the file is blank,
Does anybody know how to solve this? or there any other options than this? Thanks

react-pdf displays the pages as images. So, you have to add the domain example.com to Next image config as mentioned in https://nextjs.org/docs/basic-features/image-optimization#domains

Related

How to access data from firestore write it into a file during Nuxt build?

I'm trying to do this in the head from nuxt.config.js:
and create json file in the folder lang
import fs from 'fs'
import { db } from '../GUILLERMO-QUINTERO-ROJAS/services/firebase'
db.collection('english').doc('english').get().then((response) => {
fs.writeFile('lang/todos_1.json', JSON.stringify(response.data(), null, 2), 'utf-8', (err) => {
if (err) return console.log('An error happened', err)
console.log('File fetched from {JSON} Placeholder and written locally!')
})
})
I followed this example who works perfectly with axios request
https://stackoverflow.com/a/67689890/16899587
It's showing me this erros:
Or when I tried with this:
I wrote this code inside of the nuxtconfig.js and this worked
But I'm not sure is the best place and the best way to do, maybe you can give another ideas
hooks: {
build: {
done(builder) {
builder.nuxt.options.buildDir
const account = {
email: process.env.NUXT_ENV_FIREBASE_EMAIL,
password: process.env.NUXT_ENV_FIREBASE_PASSWORD
}
auth.signInWithEmailAndPassword(account.email, account.password).then(() => {
db.collection('english').doc('english').get().then((response) => {
fs.writeFile('lang/prueba.json', JSON.stringify(response.data(), null, 2), 'utf-8', (err) => {
if (err) return console.log('An error happened', err)
console.log('File fetched from {JSON} Placeholder and written locally!')
})
})
})
.catch((error) => {
console.log(error)
})
}
}
}
JSON file in the lang folder
OP needed to login first before using the rest of firebase's functions.

Image not found React Native (Expo)

Hello fellow programmers,
I am trying to show an image using the UserAvatar component in React-Native (Expo) but I am facing a problem where the link I am getting from the API is not working 404 Not Found, what is the best possible way to avoid this problem. I tried to create a blob using the URL of the image but it was not successful
This is the error message i am getting in the app
Online fetched source is not a supported image at node_modules/react-native-user-avatar/src/helpers.js:41:6 in fetchImage
Here is one of the solutions i have tried:
urlToBlob = (url) => new Promise((resolve, reject) => {
const xhr = new XMLHttpRequest();
xhr.onerror = reject;
xhr.onreadystatechange = () => {
if (xhr.readyState === 4) {
resolve(xhr.response);
}
};
xhr.open('GET', url);
xhr.responseType = 'blob'; // convert type
xhr.send();
})this.urlToBlob(data)
.then((blob) => {
console.log(blob);
});
The approach that i took to solve this problem is very simple.
axios
.get(image_url)
.then((res) => {
if (res.status === 200) {
setImageStatus(200);
}
})
.catch((err) => {
setImageStatus(err.response.status);
});
}
When the response status is 200 then the image exists if not fallback to the default image.

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}`,
});
});
});

How do I handle errors when responseType is blob using Vuejs?

My Question is similar to this which doesn't have an answer. I tried to search many other places but still don't have an answer.
I'm trying to download file using Axios in VueJs as a blob:
return new Promise((resolve, reject) => {
Axios.get(`${fileDownloadUrl}`,
{ responseType: 'blob' } // Blob doesn't handle errors
).then(response => {
let byteData = response.data
var blob = new Blob([byteData], {type: response.headers['content-type']})
let fileName = _.split(response.headers['content-disposition'], '=')
FileSaver.saveAs(blob, fileName[1])
resolve(fileName[1])
},
error => {
console.log(error.response.data) // returns Blob - error message from service is not handled
reject(error.response.data)
}
)
I removed the { responseType: 'blob' } from the above code and tried again, I get the error message now but the file downloaded doesn't have any content, it's a blank data.
How do I download the file and handle the error response returned by the service?
Using vue-resource solved this issue. Although it will be retiring in future releases, I couldn't find a better way to do it as Axios was not able to handle it.
Following is the code:
main.js
import VueResource from 'vue-resource'
Vue.use(VueResource)
service.js
return new Promise((resolve, reject) => {
VueResource.http.get(`${fileDownloadUrl}`,
{ responseType: 'blob' }
).then(response => {
methods.downloadFile(response, cid)
resolve(cid)
}, error => {
reject(error)
})
})
Hope this helps.
import axios from "axios";
// It is needed to handle when your response is not Blob (for example when response is json format)
axios.interceptors.response.use(
response => {
return response;
},
error => {
if (
error.request.responseType === 'blob' &&
error.response.data instanceof Blob &&
error.response.data.type &&
error.response.data.type.toLowerCase().indexOf('json') != -1
) {
return new Promise((resolve, reject) => {
let reader = new FileReader();
reader.onload = () => {
error.response.data = JSON.parse(reader.result);
resolve(Promise.reject(error));
};
reader.onerror = () => {
reject(error);
};
reader.readAsText(error.response.data);
});
}
return Promise.reject(error);
}
);
// Now you can get response in both Blob and json format
axios.get(
url,
{
responseType: 'blob'
}
).then(response => {
// Your Code
}).catch((error) => {
// Your Code
// You can get error in json format
});
May I know is it possible to use post instead of get in the following request
Axios.get(${fileDownloadUrl},
{ responseType: 'blob' }

How to get Absolute path of a file in react-native?

I am looking for a file picker in react-native which returns me Absolute Path of the file picked. I am currently using react-native-document-picker, but it gives me the relative path in the format of content://com.android.providers.media.documents/document/....... As I want to compress my video file, libraries like react-native-ffmpeg and react-native-video-processing require Absolute path of a file.
I actually figured this out myself. You can get Absolute path in 3 ways.
The most convenient way : Use react-native-document-picker, on selection it will give you a Relative path, something like this content://com.android....... Pass that Relative path to Stat(filepath) function of the react-native-fetch-blob library. The object will return absolute path. Append the path with file:// to use it for further operations.
The other 2 ways are by using react-native-image picker and CameraRoll (React Native Library)
I hope this helps !
Edit:
Please make sure you run the app on hardware device rather than Virtual Device to test it.
Install react-native-fetch-blob to get the path of the file.
Below is an example.
pickFile = async () => {
try {
const res = await DocumentPicker.pick({
type: [DocumentPicker.types.allFiles],
});
console.log(res.uri);
//output: content://com.android.providers.media.documents/document/image%3A4055
RNFetchBlob.fs
.stat(res.uri)
.then((stats) => {
console.log(stats.path);
//output: /storage/emulated/0/WhatsApp/Media/WhatsApp Images/IMG-20200831-WA0019.jpg
})
.catch((err) => {
console.log(err);
});
} catch (err) {
if (DocumentPicker.isCancel(err)) {
} else {
throw err;
}
}};
First you have to ask for Android Permissions so make sure you call this function first:
export const requestReadExternalStorage = () => {
PermissionsAndroid.request(PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE);
};
After you call this function and Permissions are accepted you can pass the uri to this function:
export const getPath = (uri: string) => {
if (uri.startsWith('content://')) {
return RNFetchBlob.fs.stat(uri).then(info => info?.path);
}
return uri;
};
Then you just need to call it and use the real uri now, like this:
// res?.uri is the uri returned from the DocumentPicker.pick() response.
const uri = await getPath(res?.uri);
You may forget to request proper permissions for that like so (andriod only):
export async function requestStoragePermission() {
if (Platform.OS !== "android") return true
const pm1 = await PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE);
const pm2 = await PermissionsAndroid.check(PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE);
if (pm1 && pm2) return true
const userResponse = await PermissionsAndroid.requestMultiple([
PermissionsAndroid.PERMISSIONS.READ_EXTERNAL_STORAGE,
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE
]);
if (userResponse['android.permission.READ_EXTERNAL_STORAGE'] === 'granted' &&
userResponse['android.permission.WRITE_EXTERNAL_STORAGE'] === 'granted') {
return true
} else {
return false
}
}
Try this, maybe it will help you https://www.npmjs.com/package/react-native-file-share-for-android
But its support only for Android
const uploadDocunment = async finalSubmit => {
const granted = await PermissionsAndroid.request(
PermissionsAndroid.PERMISSIONS.WRITE_EXTERNAL_STORAGE,
{
title: 'Storage Permission',
message: 'App needs access to memory to download the file ',
},
);
if (granted != PermissionsAndroid.RESULTS.GRANTED) {
ToastAndroid.showWithGravity(
'You need to give storage permission to download the file',
ToastAndroid.SHORT,
ToastAndroid.BOTTOM,
);
return false;
}
try {
DocumentPicker.pick({
type: [DocumentPicker.types.plainText],
}).then(res => {
RNFetchBlob.fs.readFile(res.uri, 'utf8').then(text1 => {
ToastAndroid.showWithGravity(
'Docunment is Ready!',
ToastAndroid.SHORT,
ToastAndroid.BOTTOM,
);
});
});
} catch (err) {
if (DocumentPicker.isCancel(err)) {
ToastAndroid.showWithGravity(
'File not Selected',
ToastAndroid.SHORT,
ToastAndroid.BOTTOM,
);
} else {
throw err;
}
}
};
uploadDocunment();
};