I want to load my local PDF in PDF view so i am using this plugin for that https://www.npmjs.com/package/react-native-pdf
So below is my code
let finalURL = require('../../html/html/pdf/VIVJOA-Full-Prescribing-Information.pdf')
const source = {
uri: finalURL,
cache: true,
};
<Pdf
trustAllCerts={false}
source={source}
style={styles.pdf}
/>
When i run above code in iOS it give me error like Warning: Failed prop type: Invalid prop source supplied to Pdf, expected one of type [string, number]..
Any idea how can i solve this?
add only url in the source:
let finalURL = require('../../html/html/pdf/VIVJOA-Full-Prescribing-Information.pdf')
<Pdf
trustAllCerts={false}
source={finalURL}
style={styles.pdf}
/>
Related
I am using nativescript-mediafilepicker as means of choosing a file, and this can read external storage successfully (I have downloaded a PDF to the 'downloads' folder on iOS and I am able to pick it.) I then try to load the file using the file system module from nativescript library, and this fails because it is listed as NativeScript encountered a fatal error: Uncaught Error: You can’t save the file “com.xxxxxx” because the volume is read only. This doesn't make sense as I am trying to read anyway - I don't understand where the saving part is from. The error comes from fileSystemModule.File.fromPath() line.
Something to note that file['file'] is file:///Users/adair/Library/Developer/CoreSimulator/Devices/82F397CE-B0B3-4ADD-AD52-805265C7AC49/data/Containers/Data/Application/7B47A8BD-6DBA-42CF-8792-38A8C5E61174/tmp/com.xxxxxx/test.pdf
Is the file automatically being pulled to an application specific directory after this media picker?
getFiles() {
let extensions = [];
if (app.ios) {
extensions = [kUTTypePDF]; // you can get more types from here: https://developer.apple.com/documentation/mobilecoreservices/uttype
} else {
extensions = ["pdf"];
}
const mediaFilePicker = new Mediafilepicker();
const filePickerOptions = {
android: {
extensions,
maxNumberFiles: 1,
},
ios: {
extensions,
maxNumberFiles: 1,
},
};
masterPermissions
.requestPermissions([masterPermissions.PERMISSIONS.READ_EXTERNAL_STORAGE,masterPermissions.PERMISSIONS.WRITE_EXTERNAL_STORAGE])
.then((fulfilled) => {
console.log(fulfilled);
mediaFilePicker.openFilePicker(filePickerOptions);
mediaFilePicker.on("getFiles", function (res) {
let results = res.object.get("results");
let file = results[0];
console.dir(file);
let fileObject = fileSystemModule.File.fromPath(file["file"]);
console.log(fileObject);
});
mediaFilePicker.on("error", function (res) {
let msg = res.object.get("msg");
console.log(msg);
});
mediaFilePicker.on("cancel", function (res) {
let msg = res.object.get("msg");
console.log(msg);
});
})
.catch((e) => {
console.log(e);
});
},
The issue I have experienced is resultant of the expectation of File.fromPath and what is returned by the file picker. File picker is returning a "file://path" URI, and File.fromPath is expecting a string of just "path".
Simply using the following instead is enough.
let fileObject = fileSystemModule.File.fromPath(file["file"].replace("file://","");
I am using this code and it works fine in simulator as I am getting a location and can get pdf file from there
async createPDF() {
let options = {
html: '<h1>PDF TEST</h1>',
fileName: 'test',
directory: 'Documents',
};
let file = await RNHTMLtoPDF.convert(options)
// console.log(file.filePath);
alert(file.filePath);
}
But the above code problem in the real iOS mobile as it is saving the pdf file somewhere. I don’t know where but I am not able to see that file in my mobile. So can anyone tell me how can I save my file in the downloads or documents in the iOS . So that I can see the downloaded file.
Found the answer to convert file in base64 string
You can solve this issue by using base64 as the following:
let options = {
html:
`
<h2 style="text-align: center">${'Some text and dynamic value'}</h2>
`,
fileName: 'TestingPDF',
directory: 'Documents',
base64: true
};
let file = await RNHTMLtoPDF.convert(options);
You shoud use 'react-native-file-access' to copy the file and move it to Downloads directory, so let's install it by: npm i react-native-file-access --save
Lets copy the file to the Downloads directory by the following:
const fileName = 'PMA_CurrentBalanceFile.pdf'; //whatever you want to call your file
const filePath = `${Dirs.DocumentDir}/${fileName}`;
const base64Data = file.base64; //our base64 encode file which done by RNHTMLtoPDF;
Then write the following code to do your job:
if (Platform.OS === 'android') {
const permissionGranted = await permissionWriteExternalStorage();
if (permissionGranted) {
await FileSystem.writeFile(filePath, base64Data, 'base64');
if (!FileSystem.exists(filePath)) return;// check to see if our filePath was created
await FileSystem.cpExternal(filePath, fileName,'downloads');// copies our file to the downloads folder/directory
// file should now be visible in the downloads folder
ToastAndroid.show("", "One File Downloaded", ToastAndroid.SHORT);
}
return;
}
if (Platform.OS === 'ios') {
// IOS version
await FileSystem.writeFile(filePath, base64Data, 'base64');
Alert.alert('', 'One File Downloaded');
}
I try to load the local .html file into WebView in React Native:
// load local .html file
const PolicyHTML = require('./Policy.html');
// PolicyHTML is just a number of `1`
console.log('PolicyHTML:', PolicyHTML);
// will cause an error: JSON value '1' of type NSNumber cannot be converted to NSString
<WebView html={PolicyHTML} />
The .html file should be read as a string, not as a resource representative.
How can I load the .html file into WebView in React Native?
By the way, what is the type of those resource representatives from require()? Is it number?
try it:
const PolicyHTML = require('./Policy.html');
<WebView
source={PolicyHTML}
style={{flex: 1}}
/>
I come across this post searching for loading static html.
If your html code is retrieved using, for example, an API, you can render WebView in this way:
<WebView
originWhitelist={['*']}
source={{ html: html, baseUrl: '' }}
/>
Notice that originWhitelistis required as explained in the documentation:
Note that static html will require setting of originWhitelist for
example to ["*"].
<View style={{flex: 1}}>
<WebView
style={{flex: 1}}
source={require("./resources/index.html")}
/>
</View>
To make WebView, the parent has to has a dimension or flex:1. We could set the WebView to flex: 1 too so that it fills up the parent.
If you need to serve local assets as well, then:
put all assets together with index.html into android/app/src/main/assets/www (You can copy them there with gradle task)
Then:
var uri = Platform.OS == "android" ?
"file:///android_asset/www/index.html" :
"./web/www/index.html"
return <WebView source={{ uri }} />
** For iOS didn't tested, please add instruction, how assets should be stored
With Expo tools and generally using Expo:
import { WebView } from "react-native-webview";
import { readAsStringAsync } from "expo-file-system";
import { useAssets } from "expo-asset";
export const MusicSheet = () => {
const [index, indexLoadingError] = useAssets(
require("../assets/musicsheetview/index.html")
);
const [html, setHtml] = useState("");
if (index) {
readAsStringAsync(index[0].localUri).then((data) => {
setHtml(data);
});
}
return (
<View style={styles.container}>
<WebView
onLoad={() => {}}
source={{ html }}
onMessage={(event) => {}}
/>
</View>
);
};
const styles = StyleSheet.create({
container: {
height: 100,
display: "flex",
},
});
Try this :
Add your .html file in your project.
Write such lines of code in the file where you want to use WebView Component
const OurStoryHTML = require ('./OurStory.html')
<WebView
source={OurStoryHTML}
style={{flex: 1, marginTop : 44}}
/>
It may help you.
If you're working with assets, project directories is different on the device's directory once the project is build and you can't simply reference them via string url.
Expo
If using expo, you have to require every asset then use useAssets on the require to cache them to the local storage of the device.
useAssets will return an object that contains a localUri
(this is the uri of the image that has been cached)
you can then use the localUri and put it as the src of the image
import { useAssets } from 'expo-asset';
/* . . . */
const IndexHTML = require('./assets/index.html');
const myImage = require('./assets/splash.png');
// url link after image is cached to the device
const [imgSrc, setImgSrc] = useState('');
const [image, imerr] = useAssets(myImage);
const [html, error] = useAssets(IndexHTML);
const webViewProps = {
javaScriptEnabled: true,
androidLayerType: 'hardware',
originWhitelist: ['*'],
allowFileAccess: true,
domStorageEnabled: true,
mixedContentMode: 'always',
allowUniversalAccessFromFileURLs: true,
onLoad: () => {
console.log(image[0].localUri);
setImgSrc(image[0].localUri);
},
source: {
html: '<img src="' + imgSrc + '"/>',
},
};
return <WebView {...webViewProps} />
const webViewProps = {
...
source: IndexHTML,
};
Note: for the expo apporach, files referenced in IndexHTML will not be found
The trick is to turn your html into a string literal to utilize template strings.
Then you have to manually require each of those assets to concatenate localUrl
require() has limited types supported and you need to add a metro.config.js in your root folder.
it will give errors if you require() a .js file since it reads it as a module rather, the workaround approach would be to bundle your assets
const { getDefaultConfig } = require('expo/metro-config');
const config = getDefaultConfig(__dirname);
config.resolver.assetExts.push(
// Adds support for asset file types
'css', 'ppt', 'obj'
);
module.exports = config;
Moreover, expo can hot reload changes done with the cached assets.
React Native
If you have the android folder in your directory, navigate to
android > app > build.gradle
then add
android {
/* link assets to the local storage of device */
sourceSets {
main { assets.srcDirs = ['src/main/assets', '../../source/assets/'] }
// [do not touch, 'relative to your asset'] }
}
. . .
finally, the relative folder you linked in gradle can be accessed through
file:///android_asset/
for ex. file:///android_asset/index.html -> /asset/index.html
return <WebView source={{uri: `file:///android_asset/index.html`}} />
For IOS, here's how
On the other hand, you have to rebuild vanilla react to see the changes in the assets.. which takes about 20 minutes or so
Alternative
A quick solution would be to integrate a static server, but this is a recent fork of the react-native-static-server that only works in vanilla react native.
I need to send the image file using multipart request from Lightroom to my local web service using Lua language.
I have tested using sending headers also but not working...
I have created a function :
function testupload(filepath) --created inside LrTasks
local url = "http://localhosturl"
local mycontent = {
{
name = "lightroom_message",
value = "sent from lightroom plugin multiparta"
},
{
name = 'file',
filePath = filepath,
fileName = LrPathUtils.leafName(filepath),
contentType = 'image/jpeg'
--contentType = 'multipart/form-data'
}
}
local response, headers = LrHttp.postMultipart(url, mycontent)
end
But my web service is not getting called properly and I am using LrHttp.postMultipart() method to do so..
If I am sending just this param to web service (then working fine):
{
name = "lightroom_message",
value = "sent from lightroom plugin multiparta"
}
but when I include my file payload then its not working using pure Lua implementation.
Everything was correct but just a technical mistake...I was trying to call the testupload() function from inside LRtasks..but we dont need to call it in separate task and the function works perfect
I'm almost there, but I'm having an issue with decoding of the file. When decoding the file is not correct.
The code that I use to upload the file:
createDataSet: function() {
var data = new FormData();
data.append('original_filename', this.get('fileName'));
data.append('datafile', this.get('newData'));
data.append('project_id', this.get('content.id'));
data.append('name', this.get('content.name'));
$.ajax({
url: '/data_sets.json',
data: data,
cache: false,
contentType: false,
processData: false,
dataType: 'json',
type: 'POST',
success: function(data) {
alert('ok');
},
error: function(xhr, data, errorThrown) {
alert('error');
}
});
}
On the Rails side I'm trying to pick this up with the following method:
def create
# take care of the attachement
datasetfilename = Pathname.new(params[:original_filename]).basename
newfile = File.open(datasetfilename, 'w') do |f|
f.write(Base64.decode64(params[:datafile]))
end
#dataset = DataSet.new
#active_data_set = #dataset.active_data_sets.build
#active_data_set.project_id = params[:project_id]
#active_data_set.save
#dataset.name = params[:name]
#dataset.filename = datasetfilename
#dataset.tempfilename = #dataset.savefile newfile
#dataset.save
end
If I use File.open(datasetfilename, 'w') I get an error like this one Encoding::UndefinedConversionError - "\xAB" from ASCII-8BIT to UTF-8. On the other hand, if I open with 'wb' the resulting file is mingled and can't be read.
I already added the meta tag for the file encoding <meta charset="utf-8" /> but without any difference.
If anybody has any hint that would be appreciated.
Just got this working in one of my own controllers, there are 2 main issues:
1) to resolve the encoding issue, use "w:binary" as the write flag instead of "w" (defaults to ASCII)
2) the :datafile params includes some header info "data:text/csv;base64,SUR4CUluZ...", I'm currently splitting on "," but might be better served to decode everything beyond "base64," as I'm not sure if additional commas are allowed.
My working code (slightly different parameter names):
if params.key?(:img_file)
header, data = params[:img_file].split(',')
img_type = header.match(/image\/([a-z]{1,11});/)[1]
file_path = "imgtodo/fund_#{#fund.id}.#{img_type}"
File.open(Rails.root.join('public',file_path).to_s, 'w:binary') do |f|
f.write(Base64.decode64(data))
end
end