react-pdf from ByteArray response? - javascript

I am trying to request a PDF file from my java server through a react typescript app. Then trying to display this byte[] through react-pdf.
The request to the server looks like this:
const [invoice, setInvoice] = React.useState<any>()
const downloadPdf = (theInvoice: Invoice) => {
store.app.cubaRest?.invokeService<any>('billing_InvoiceService', 'generateInvoiceDocument', { invoice: theInvoice })
.then((response: any) => {
console.log(response)
let array= JSON.parse(response).content
setInvoice(array)
}).finally(()=>{
})
}
if (invoice) {
console.log("there is invoice")
return (
<div>
<Document
file={{ data: invoice }}
onLoadSuccess={onDocumentLoadSuccess}
onLoadError={console.error}
>
<Page pageNumber={pageNumber} />
</Document>
</div>
The console log from the raw "response" above looks like this:
{"report":{"_entityName":"report$Report","id":"1dd6746f-3580-6e3c-3aa6-e3f5db0a290b","code":"default-invoice","roles":[],"defaultTemplate":{"id":"0de287de-1931-a375-d10f-70ae431a3ca7","content":"PD94bWwgdmVyc2lvbj0iMS4wIiBlbmNvZGluZz0iVVRGLTgiPz4KPCEtLSBDcmVhdGVkIHdpdGggSmFzcGVyc29mdCBTdHVkaW8gdmVyc2lvbiA2LjE2LjAuZmluYWwgdXNpbmcgSmFzcGVyUmVwb3J0cyBMaWJyYXJ5IHZlcnNpb24gNi4xNi4wLTQ4NTc5ZDkwOWI3OTQzYjY0NjkwYzY1YzcxZTA3ZTBiODA5ODE5MjggIC0tPgo8amFzcGVyUmVwb3J0IHhtbG5zPSJodHRwOi8vamFzcGVycmVwb3J0cy5zb3VyY2Vmb3JnZS5uZXQvamFzcGVycmVwb3J0cyIgeG1sbnM6eHNpPSJodHRwOi8vd3d3LnczLm9yZy8yMDAxL1hNTFNjaGVtYS1pbnN0YW5jZSIgeHNpOnNjaGVtYUxvY2F0aW9uPSJodHRwOi8vamFzcGVycmVwb3J0cy5z .......
When I set the state from the response the page just keeps rerendering and the pdf does not show. Presumably it is doing a re-render for every byte in the byte array.
Not sure how to resolve this. Also not sure if I am sending the byte[] correctly to setInvoice either. Or if the byteArray is in the correct format for that matter.

Was quite a simple solution.
instead of:
let array= JSON.parse(response).content
setInvoice(array)
do:
setInvoice({data: JSON.parse(response).content});
if (invoice) {
return (
<div>
<Document
file={invoice}
onLoadSuccess={onDocumentLoadSuccess}
onLoadError={console.error}
>
<Page pageNumber={pageNumber} />
</Document>
</div>

Heres the base64 approach
1. Given base64 string of the pdf file
const fileAsBase64 = || YOUR PDF FILE IN BASE64 AS STRING ||
2. Convert base64 string to bytearray
export const base64ToArrayBuffer = (base64) => {
const binaryString = window.atob(base64); // Comment this if not using base64
const bytes = new Uint8Array(binaryString.length);
return bytes.map((byte, i) => binaryString.charCodeAt(i));
}
3. Add the byearray to component by calling above function
<Document file={{ data :base64ToArrayBuffer(base64)}}/>

Related

Render docx in React js

I would like to properly render a docx file in React JS with the correct formatting, as it would appear in Word or a similar service. Currently, when displaying the text, all formatting is removed and appears as plain text. I obtain the file from the server, and process it, by:
const url = "http://localhost:8080/files/aboutme.docx";
axios.get(url, {
responseType: 'arraybuffer',
}).then(response => {
var doc = new Docxtemplater(new PizZip(response.data), {
delimiters: {
start: 'ran',
end: 'ran'
}
});
var text = doc.getFullText();
setAboutMe(text);
})
I am using the Docxtemplater and PizZip libraries.
Docxtemplater is
a library to generate docx/pptx documents from a docx/pptx template
If you need to render a docx file I think you should use react-doc-viewer. Then you could write something like:
import DocViewer from "react-doc-viewer";
function App() {
const doc = [{ uri: "http://localhost:8080/files/aboutme.docx" }];
return <DocViewer documents={doc} />;
}

How to post data as html formatted text

I have a front-end react application posting data to a server. Using CKEditor and React Hook Form. When I console.log the data prior to posting I get the ideal html formatted text ( <p><strong> ). However, when I check the data I see html entities ( <p>...s<strong> ). I'd like the server to receive the data as I see it in the front end, as html formatted text, so I can show it properly in other parts of the app. Here's the relevant code.
CreateArticle.jsx
...
const [ckData, setCkData] = useState(null)
...
const onSubmit = data => {
// place tags into an array
modifyTag(data);
// retrive data from CKEditor, place into 'content'
modifyContent(data)
// 'content shows as html formatted text as intended
console.log(data)
// imported create article (POST) from axios.js
createArticle(data)
.then(res => {
const id = res.data.data.id;
setArticleId(id);
})
.catch(err => console.log(err.response.data.error))
}
...
const modifyContent = (data) => {
// React Hook Form troubles with CK and handleSubmit
// manually replace content with ckData
data.content = ckData
}
...
<Controller
as={<CKEditor
editor={ClassicEditor}
onBlur={(event, editor) => {
//save data to content variable
const content = editor.getData();
//save content to CkData hook
setCkData(content)
}}
/>}
name="content" control={control}
/>
...
Is there a front end solution to this?

Get contents of a zip file

This URL below points to a zip file which contains a file called bundlesizes.json. I am trying to read the contents of that json file within my React application (no node server/backend involved)
https://dev.azure.com/uifabric/cd9e4e13-b8db-429a-9c21-499bf1c98639/_apis/build/builds/8838/artifacts?artifactName=drop&api-version=4.1&%24format=zip
I was able to get the contents of the zip file by doing the following
const url =
'https://dev.azure.com/uifabric/cd9e4e13-b8db-429a-9c21-499bf1c98639/_apis/build/builds/8838/artifacts?artifactName=drop&api-version=4.1&%24format=zip';
const response = await Axios({
url,
method: 'GET',
responseType: 'stream'
});
console.log(response.data);
This emits the zip file (non-ascii characters). However, I am looking to read the contents of the bundlesizes.json file within it.
For that I looked up jszip and tried the following,
var zip = new JSZip();
zip.createReader(
new zip.BlobReader(response.data),
function(reader: any) {
// get all entries from the zip
reader.getEntries(function(entries: any) {
if (entries.length) {
// get first entry content as text
entries[0].getData(
new zip.TextWriter(),
function(text: any) {
// text contains the entry data as a String
console.log(text);
// close the zip reader
reader.close(function() {
// onclose callback
});
},
function(current: any, total: any) {
// onprogress callback
console.log(current);
console.log(total);
}
);
}
});
},
function(error: any) {
// onerror callback
console.log(error);
}
);
However, this does not work for me, and errors out.
This is the error I receive
How can I read the contents of the file within the zip within my React application by using Javascript/Typescript?

Force fetched image data to https

I am looking for a solution to force images from a fetch API to be in https rather than http
The API returns image results as http from the fetched JSON file but this is giving warning in the console to Mixed Content
I am fetching in componentDidMount as
componentDidMount() {
var self = this;
const proxyurl = 'https://cors-anywhere.herokuapp.com/';
const url = `//api.tripadvisor.com/api/partner/2.0/location/${this.props
.tripAdvisorId}?key=${AuthKey}`;
fetch(proxyurl + url)
.then(data => data.json())
.then(data => {
self.setState({
reviewData: data,
isLoading: false
});
});
}
and then mapping the data by way
{this.state.reviewData.reviews.map(i => {
return (
<div key={i.id}>
<img src={i.rating_image_url} alt={i.title} />
</div>
);
})}
How can I force the url from {i.rating_image_url} to use https when this is not returned from the fetch?
By using a regular expression, something like:
{this.state.reviewData.reviews.map(i => {
return (
<div key={i.id}>
<img src={i.rating_image_url.replace(/^http:\/\//i, 'https://')} alt={i.title} />
</div>
);
})}
const url = new URL(originalUrl);
url.protocol = url.protocol.replace('http', 'https');
console.log(url.href);
This method uses the built-in URL class to fully parse, and then uses a string replacement on the protocol.
Just change this code to check if you are receiving the image or not
<img src={i.rating_image_url ? i.rating_image_url : i.rating_image_url.replace(/^http:\/\//i, 'https://')} alt={i.title} />
This way we are checking if we are getting its value or not.
For more better understanding you can also do this
{this.state.reviewData.reviews.map(i => {
console.log(i.rating_image_url);
return (
<div key={i.id}>
<img src={i.rating_image_url} alt={i.title} />
</div>
);
})}
This will show whatever data you are receiving in rating_image_url on your browser console.
Hope it helps you.

React-native - Populate image with Blob that has been converted to a URL

I want to populate an image with a uri.
I request the image from the server and it returns a BLOB.
BLOB when displayed to console:
I then convert the BLOB into a URL with the following line:
var blobUrl = URL.createObjectURL(blob);
blobUrl when displayed to console
I then try and populate the Image with the URL:
<Image source={{uri: blobURL}} style={{width: 100, height: 50}} />
The image will not display. What should I do?
I am using the android emulator which is connected to the localhost. Could possibly have something to do with that seen as the BLOB url would be stored to the localhost?
Or it could be a simple syntax error?
Thanks.
Solution
React-Native does not support blobs [ref: Git/React-Native]. In order to get this working I had to download react-native-fetch-blob which returns a base64 string.
Function that returns base64 string:
var RNFetchBlob = require('react-native-fetch-blob').default;
getImageAttachment: function(uri_attachment, mimetype_attachment) {
return new Promise((RESOLVE, REJECT) => {
// Fetch attachment
RNFetchBlob.fetch('GET', config.apiRoot+'/app/'+uri_attachment)
.then((response) => {
let base64Str = response.data;
var imageBase64 = 'data:'+mimetype_attachment+';base64,'+base64Str;
// Return base64 image
RESOLVE(imageBase64)
})
}).catch((error) => {
// error handling
console.log("Error: ", error)
});
},
Populate Image with base64
I then populate the image withe the returned base64Image with:
<Image source={{uri: imageBase64}} style={styles.image} />
After you have received the blob:
let imageUri = "data:image/png;base64," + blob;
<Image source={{uri: imageUri, scale: 1}} style={{height: 30, width: 30}}/>
May be solved by react-native-fetch-blob, it's about issue #854

Categories

Resources