Fetch Editable Updated Content of Iframe from Blob URL with PDF-LIB - javascript

I am trying to implement below feature using ReactJS and PDF_LIB.
Load PDF in Iframe from source URL -> PDF is editable test fields and then submit updated PDF to nodejs Server.
I achieved :
I render Iframe in ReactJS.
I used PDF_LIB js library to load PDFDocument and create Blob url for local change.
Issue:
On submit, Didn't get updated PDF content from Blob URL.
how can we get updated content from same Blob URL ?
Below code is for initialization of PDF.
const intializePdf = async () => {
const url = 'https://pdf-lib.js.org/assets/with_update_sections.pdf'
const arrayBuffer = await fetch(url).then(res => res.arrayBuffer())
const pdfDoc = await PDFDocument.load(arrayBuffer)
const pdfBytes = await pdfDoc.save();
const blobObj = new Blob([pdfBytes], { type: "application/pdf" })
const docUrl = URL.createObjectURL(blobObj);
setPdfInfo(docUrl);
}
Below code for Submit PDF to Server
const submitPdf = async () => {
const url = pdfInfo
const arrayBuffer = await fetch(url).then(res => res.arrayBuffer())
const pdfDoc = await PDFDocument.load(arrayBuffer)
pdfContentToParent(await pdfDoc.save())
}
On above code of "pdfDoc" is still don't have any updated fields.

Related

How to correctly display images on React frontend that are returned by Laravel as StreamedResponse objects?

The idea is as follows:
Images/documents are stored privately on the server
A logged-in user on frontend clicks a button which sends an axios request to backend to get an aggregated result of ModelA from TableA and it's associated attachment file list from TableB
For each ModelA, numerous requests are made to endpoint to fetch images which are returned as \Symfony\Component\HttpFoundation\StreamedResponse via Storage::download($request->file_name)
This works in the sense that files are returned.
Note - I tried attaching all files to response in step 2 but this didn't work, so added the extra step to get file list and get individual files after that based on the list. This might kill the webserver if the amount of requests becomes too high, so would appreciate any advise on a different approach.
The problem
How to display the files in React and is this the right approach at all considering potential performance issues noted above?
I've tried the following:
Create an octet-stream url link with FileReader but these wouldn't display and had the same url despite await being used for the reader.readAsDataURL(blob) function:
const { email, name, message, files } = props
const [previews, setPreviews] = useState<string[]>([])
const { attachments } = useAttachment(files)
useEffect(() => {
const p = previews
files && attachments?.forEach(async filename => {
const reader = new FileReader()
reader.onloadend = () => {
p.push(reader.result as string)
setPreviews(p)
}
const blob = new Blob([filename])
await reader.readAsDataURL(blob)
})
}, [files, attachments, previews])
Create src attributes with URL.createObjectURL() but these, although generated and unique, wouldn't display when used in an <img /> tag:
useEffect(() => {
const p = previews
files && attachments?.forEach(filename => {
const blob = new Blob([filename])
const src = URL.createObjectURL(blob)
p.push(src)
setPreviews(p)
})
}, [files, attachments, previews])
Results example:
<img src="blob:http://127.0.0.1:8000/791f5efb-1b4e-4474-a4b6-d7b14b881c28" class="chakra-image css-0">
<img src="blob:http://127.0.0.1:8000/3d93449e-175d-49af-9a7e-61de3669817c" class="chakra-image css-0">
Here's the useAttachment hook:
import { useEffect, useState } from 'react'
import { api } from '#utils/useAxios'
const useAttachment = (files: any[] | undefined) => {
const [attachments, setAttachments] = useState<any[]>([])
const handleRequest = async (data: FormData) => {
await api().post('api/attachment', data).then(resp => {
const attach = attachments
attach.push(resp)
setAttachments(attach)
})
}
useEffect(() => {
if (files) {
files.forEach(async att => {
const formData = new FormData()
formData.append('file_name', att.file_name)
await handleRequest(formData)
})
}
}, [files, attachments])
return { attachments }
}
export default useAttachment
Try Storage::response(). This is the same as Storage::download() just that it sets the Content-Disposition header to inline instead of attachment.
This tells the browser to display it instead of downloading it. See MDN Docs Here
Then you can use it as the src for an <img/>.
Solved it by sending the files in a single response but encoded with base64encode(Storage::get('filename')). Then, on the frontend, it was as simple as:
const base64string = 'stringReturned'
<img> src={`data:image/png;base64,${base64string}`}</img>```

How to download file directly in node response in react?

How do I download the document I receive in return in react?
Here is the my node.js app. fetchContracts is a function which getting data from mongodb then ganere a excel file by using json2xls npm package.
Its returns as like this:
const xls = json2xls(contracts);
return xls;
If tying to write file fs.writeFileSync(path.join(__dirname, filename), xls, 'binary'); generating successfully xlsx file in the server.
But I need to send the file to the server without writing file. For this, I made some experiments that you can see below.
export const EXPORT_EXCEL: SessionedAsyncControllerType = async (req: SessionedRequest, res: Response) => {
const fileName = 'hello_world.xlsx'
const fileType = 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'
const xls = await fetchContracts({}, "fileName.xlsx")
const fileData = xls;
res.writeHead(200, {
'Content-Disposition': `attachment; filename="${fileName}"`,
'Content-Type': fileType,
})
const download = Buffer.from(fileData, 'base64')
res.end(download)
}
I getting response like this.
But i don't know how can i download the response file in react?
In react side:
return api.get(`api/excel`).then((response: any) => {
console.log(response);
})
I just log into console. How can i download directly file which coming node response in react.js?
Try this
return api.get(`api/excel`).then((response: any) => {
const outputFilename = `${Date.now()}.xlsx`;
// If you want to download file automatically using link attribute.
const url = URL.createObjectURL(new Blob([response.data]));
const link = document.createElement('a');
link.href = url;
link.setAttribute('download', outputFilename);
link.click();
})

Uploading an mp3 to Firebase Storage with React Native Expo

I am attempting to upload an mp3 to firebase storage using expo and react native. So far I've got the file into firebase storage, but it's only 9bytes large, so I'm doing something wrong. I've attempted this with blob as shown below with no success.
Here is a screenshot of the firebase storage folder showing the file uploaded but not the data of said file:
Any help is greatly appreciated, I feel like I'm missing a step to actually upload the data along with the file.
export default function SongPicker() {
const [song, setSong] = useState(null);
//Get current user through authentication
const user = auth.currentUser;
const pickDocument = async () => {
let result = await DocumentPicker.getDocumentAsync({});
// Fetch the photo with it's local URI
const response = fetch(result.uri);
alert(result.uri);
console.log(result);
const file = new Blob(
[response.value], {
type: 'audio/mpeg'
});
console.log('do we see this?');
try {
//Create the file reference
const storage = getStorage();
const storageRef = ref(storage, `songs/${user.uid}/${result.name}`);
// Upload Blob file to Firebase
const snapshot = uploadBytes(storageRef, file, 'blob').then((snapshot) => {
console.log('Uploaded a song to firebase storage!');
});
setSong(result.uri);
} catch (error) {
console.log(error);
}
}
The fetch() returns a Promise so you should add an await for that as well.
const response = await fetch(result.uri);
Then try using blob() method on the Response:
const file = await response.blob()
The third param in uploadBytes should be upload metadata object but you can skip that here:
const snapshot = await uploadBytes(storageRef, file).

How to get download url for a Image from Firebase Storage?

I am trying to upload an image to firebase storage after that I am trying to get the download url of image but it's not working. Below is the code :
const response = await fetch(selectedImage.uri);
const file = await response.blob();
const storageRef = ref(storage, `profile/${currentUser.email}`);
uploadBytes(storageRef, file).then( (snapshot) => {
console.log('uploaded');
getDownloadURL(storage).then( url => console.log(url)); // tried this outside of then block as well
});
the file is uploaded and accessible through console but getDownloadURL throws error :
[Unhandled promise rejection: TypeError: ref._throwIfRoot is not a function. (In 'ref._throwIfRoot('getDownloadURL')', 'ref._throwIfRoot' is undefined)]
Instead of passing storage to getDownloadURL(), pass snapshot.ref.
const response = await fetch(selectedImage.uri);
const file = await response.blob();
const storageRef = ref(storage, `profile/${currentUser.email}`);
uploadBytes(storageRef, file).then( (snapshot) => {
console.log('uploaded');
getDownloadURL(snapshot.ref).then( url => console.log(url));
});

How to get file contents from ipfs-http-client

I am using ipfs-http-client to read the contents of a file form infura, how do i use the "cat" funtionality to correctly get the data in a string/json format?
const client = create({
url: ipfsUrl(),
headers: {
authorization: ipfsAuthPhrase(),
},
});
const cidformat = "f" + cid.substring(2);
const cidV0 = new CID(cidformat).toV0().toString();
const resp = await client.cat(cidV0);
let content = [];
for await (const chunk of resp) {
content = [...content, ...chunk];
}
console.log(content.toString());
right now i am just getting a array of binaries on the console log.
From this point on its just a matter of decoding the content buffer.
If the content is some JSON:
const raw = Buffer.from(content).toString('utf8')
console.log(JSON.parse(raw))
If the content is an image:
Buffer.from(content).toString('base64')

Categories