View or open PDF files stored locally Expo React Native - reactjs

Is there a solution to view or open PDF Files using Expo (without Expo eject)?
It's not necessary to open file inside App, it's can be a local filemanager.
What i tried:
Linking does not open locally files, only online sources
React Native PDF doesn't work with expo
Expo Media Library allows to download files, but not open it.

My solution:
Use FileSystem.getContentUriAsync() and Expo IntentLauncher
import * as FileSystem from 'expo-file-system';
import * as IntentLauncher from 'expo-intent-launcher';
FileSystem.getContentUriAsync(uri).then(cUri => {
IntentLauncher.startActivityAsync('android.intent.action.VIEW', {
data: cUri.uri,
flags: 1,
type: 'application/pdf'
});
});

I tried this solution https://stackoverflow.com/a/59813652/16799160 and I get this error:
[Unhandled promise rejection: Error: Encountered an exception while calling native method: Exception occurred while executing exported method startActivity on module ExpoIntentLauncher: No Activity found to handle Intent { act=android.intent.action.VIEW typ=application/pdf flg=0x1 }]
After that, I modified data: cUri.uri to data: cUri based on expo doc and works fine.
Remember, this is an android-only solution
import * as FileSystem from 'expo-file-system';
import * as IntentLauncher from 'expo-intent-launcher';
try {
const cUri = await FileSystem.getContentUriAsync(uri);
await IntentLauncher.startActivityAsync("android.intent.action.VIEW", {
data: cUri,
flags: 1,
type: "application/pdf",
});
}catch(e){
console.log(e.message);
}

import * as FileSystem from 'expo-file-system';
import * as IntentLauncher from 'expo-intent-launcher';
const uri = FileSystem.documentDirectory + 'Example'.xlsx;
FileSystem.getContentUriAsync(uri).then(cUri => {
console.log(cUri);
IntentLauncher.startActivityAsync('android.intent.action.VIEW', {
data: cUri,
flags: 1,
});
});
Note: get your filelocation on uri

Related

Fetching a github repo in react gives a "Module "stream" has been externalized for browser compatibility and cannot be accessed in client code" error

I am currently stuck with a problem trying to fetch github repo data using the octokit npm package.
I use vite to run a dev server and when I try to make a request, the error that i get is:
Uncaught Error: Module "stream" has been externalized for browser compatibility and cannot be accessed in client code.
My React .tsx file looks like this:
import { Octokit, App } from 'octokit'
import React from 'react'
const key = import.meta.env.GITHUB_KEY
const octokit = new Octokit({
auth: key
})
await octokit.request('GET /repos/{owner}/{repo}', {
owner: 'OWNER',
repo: 'REPO'
})
export default function Repos() {
return (
<>
</>
)
}
I have redacted the information for privacy purposes.
If anyone knows how to resolve this issue with vite, please let me know!
Check first if this is similar to octokit/octokit.js issue 2126
I worked around this problem by aliasing node-fetch to isomorphic-fetch. No idea if it works for all usages within octokit, but works fine for my project.
You'll need to install the isomorphic-fetch dependency before making this config change.
// svelte.config.js
const config = { // ... kit: {
// ...
vite: {
resolve: {
alias: {
'node-fetch': 'isomorphic-fetch',
},
},
},
},
};
export default config;
Note: there are still questions about the support/development of octokit: issue 620.

I export my data to Excel but i get this error: Cannot read properties of undefined (reading 'editing')

I Want to export my material table data to Excel but when I click to download I get error in console:
Cannot read properties of undefined (reading 'editing')
(I use "xlsx": "^0.18.0")
<div onClick={downloadExcel} className="downloadExcel">
<img src="/assets/excel-svgrepo-com.svg" />
</div>
and my downloadExcel function is:
const downloadExcel = () => {
const newData = Apiary.map((row) => {
delete row.tableData;
return row;
});
const workSheet = XLSX.utils.json_to_sheet(newData);
const workBook = XLSX.utils.book_new();
XLSX.utils.book_append_sheet(workBook, workSheet, "students");
//Buffer
let buf = XLSX.write(workBook, { bookType: "xlsx", type: "buffer" });
//Binary string
XLSX.write(workBook, { bookType: "xlsx", type: "binary" });
//Download
XLSX.writeFile(workBook, "لیست زنبورستان.xlsx");
};
when I onClick img my react is freeze and stop
How can I fix this error?
TL;DR: Make sure you import the XLSX library like this: import * as XLSX from 'xlsx'
I had a similar issue with the XLSX on Vue.js.
I was importing the lib on a component with import XLSX from 'xlsx' and getting this error on the console:
[Vue warn]: Error in v-on handler: "TypeError: Cannot read properties of undefined (reading 'utils')"
And then I noticed on the terminal (which was running the vue.js app) the message: "export 'default' (imported as 'XLSX') was not found in 'xlsx'
So I've resolved it by changing the import to: import * as XLSX from 'xlsx'
Problem seems to be because of xlsx version. There are some breaking changes between 0.18.0 and 0.15.1.
I was able to solve the issue in three ways:
By importing xslx dependency with file extension(with newer version of xlsx) like below:
import * as XLSX from 'xlsx/xlsx.js;
Actually, in newer version of xlsx, there are two files available, i.e, xlsx/xlsx.js and
xlsx/xlsx.mjs. By default, app tries to load .mjs file while .mjs files are not importable by default.
By explicitly defining config to allow import of .mjs files in the app.
By using lower version of xlsx across whole project. xlsx version 0.15.1 will work.

Nextjs API works in local environment but not in production environment

[SOLVED]
I have created a dynamic API route in NextJS that, if given a filename, the server will read the file (.md or .txt file) under the content directory, convert it into string and returns it. The API works as intended in local environment, however, the deployed website in Vercel doesn't work properly for this API route.
That API route, for a file that exists in the content directory, returns 500 internal server error.
The console error is:
Failed to load resource: the server responded with a status of 500 ()
Checking the vercel logs for the route, showed this:
ERROR Error: ENOENT: no such file or directory, open 'content/phase1_section1.md'
I think the path.join() is not working for me. It is not adding the actual domain name of the app in front of the content part. How can I resolve this?
And, here's the code
import { readFileSync } from 'fs';
import path from "path";
export default function courseHandler({ query: { slug } }, res) {
const fullPath = path.join('./content/', slug);
const content = readFileSync(fullPath, 'utf8');
if (content) {
res.status(200).json({
content: content
});
} else {
res.status(404).json({ message: `Course with slug: ${slug} not found.` })
}
}
The problem is actually solved.
I just replaced this
path.join('./content/', slug);
with this
path.join(process.cwd(), 'content', slug);
Check logs on Vercel
Configure yours .env variables on Vercel for each environment
Check your local .env files. if you hardcoded your .env variables - this will cause a negative impact.

Accessing file in public folder through capacitor

I'm using ionic-v5, capactior and react to build an app.
I have a file (data.json) stored inside of my public/ folder.
I simply want to be able to load that file in and store it as an object.
So far I have tried:
import { Filesystem, FilesystemEncoding } from '#capacitor/core'
let contents = await Filesystem.readFile({
path: "data.json",
encoding: FilesystemEncoding.UTF8,
})
import { HTTP } from '#ionic-native/http';
let response = await HTTP.get("file://data.json", {}, {});
ret = response.data;
return ret;
I have also looked at https://ionicframework.com/docs/native/file but the documentation is poor to say the least.
Along with this I have tried pre-pending /android_asset/public to all of the paths but no luck (I know it would only work on Android, I just wanted to get something).
If you're using Ionic React (v5) and you just want to access a file in /myapp/public, you don't need Capacitor.
You can use axios (or fetch).
Folder structure:
/myapp
/assets
/json
/myFile.json
Sample code:
// https://stackoverflow.com/a/52570060
export const fetchJsonFile = (fileName: string): Promise<any> => (
axios.get(`./json/${fileName}`)
.then((response) => response).catch((error) => {
Promise.reject(error);
})
);

Ionic 2 File Plugin usage examples

Does anyone have complete examples about how to use the Cordova Native File Plugin in a Ionic 2/Angular 2 project?
I installed this plugin but the documentation don't seems to make much sense to me due the fact it is fragmented and lacks of a complete example, including all needed imports.
For example, the following example don't shows where objects like LocalFileSystem or window came from.
window.requestFileSystem(LocalFileSystem.PERSISTENT, 0, function (fs) {
console.log('file system open: ' + fs.name);
fs.root.getFile("newPersistentFile.txt", { create: true, exclusive: false }, function (fileEntry) {
console.log("fileEntry is file?" + fileEntry.isFile.toString());
// fileEntry.name == 'someFile.txt'
// fileEntry.fullPath == '/someFile.txt'
writeFile(fileEntry, null);
}, onErrorCreateFile);
}, onErrorLoadFs);
For example, I need to crate a property file. First I need to check if a file exists on app sandbox storage area, if don't exists I must create it. Then I must open the file write data and save it . How could I do that?
Ionic 2 comes with a Cordova file plugin wrapper:
http://ionicframework.com/docs/v2/native/file/.
The necessary file system paths (e.g. cordova.file.applicationDirectory) you can find here at the documentation of the original plugin:
https://github.com/apache/cordova-plugin-file#where-to-store-files. Note that not all platforms support the same storage paths.
I even managed to build a file browser with it. Use it like so:
import {Component} from '#angular/core';
import {File} from 'ionic-native';
...
File.listDir(cordova.file.applicationDirectory, 'mySubFolder/mySubSubFolder').then(
(files) => {
// do something
}
).catch(
(err) => {
// do something
}
);
Here is an example using IonicNative for an app I am working on where I want
to send an email with a csv file attachment.
import {EmailComposer} from '#ionic-native/email-composer';
import {File} from '#ionic-native/file';
class MyComponent {
constructor(private emailComposer: EmailComposer, private file: File) {
}
testEmail() {
this.file.writeFile(this.file.dataDirectory, 'test.csv', 'hello,world,', {replace: true})
.then(() => {
let email = {
to: 'email#email',
attachments: [
this.file.dataDirectory + 'test.csv'
],
subject: 'subject',
body: 'body text...',
isHtml: true
};
this.emailComposer.open(email);
})
.catch((err) => {
console.error(err);
});
}
}
This was tested with ionic 3.7.0 on IOS.

Resources