I've been been trying to print an existing pdf file which is in sd card.
So i added printing package to my flutter project to print pdf files.
Printing package link
I checked their documentation and i can't find a way to load and print pdf.
Fyi, i can create a pdf from image, text or whaetever it is and pass it to the Printing function. That works as anticipated.
final pdf = Document();
pdf.addPage(Page(
pageFormat: PdfPageFormat.a4,
build: (Context context) {
return Center(
child: Text("Hello World"),
);
})
);
await Printing.layoutPdf(onLayout: (PdfPageFormat format) async => pdf.save());
Any help to load existing pdf and print would be appreciable
Thanks
I finally find a way to print pdf using printing plugin.
You can directly print pdf by giving the online pdf url
To do so, just use the following dart snippet
http.Response response = await http.get('http://www.africau.edu/images/default/sample.pdf');
var pdfData = response.bodyBytes;
await Printing.layoutPdf(onLayout: (PdfPageFormat format) async => pdfData);
Don't forget to import http plugin
import 'package:http/http.dart' as http;
Thanks everyone for the help
Including the other answers:
BTW, I have an another answer regarding this topic
Directly print from a URL
var data = await http.get(url);
await Printing.layoutPdf(onLayout: (_) => data.bodyBytes);
SharePdf function
var data = await http.get(url);
await Printing.sharePdf(bytes: data.bodyBytes, filename: 'your-document.pdf');
This one needs an extra one step to print.
View from the browser
Use this package url_launcher, open in a browser view, then print it
import 'package:url_launcher/url_launcher.dart';
if (await canLaunch(url)) {
await launch(url);
}
This solution needs an extra one step to print as well.
The flutter_pdf_printer package.
Use this package flutter_pdf_printer and path_provider
var data = await http.get(url);
final output = await getTemporaryDirectory();
final file = File('${output.path}/your_file_name_${new DateTime.now().microsecondsSinceEpoch}.pdf');
await file.writeAsBytes(data.bodyBytes);
await FlutterPdfPrinter.printFile(file.path);
*** this package will have channel registrant issue, please run flutter clean after installation ***
This package is a little bit outdated, but it works for me to print with a roller 80 size pdf. It uses the Swift UIKit package, which has good compatibility.
Welcome add comments.
This will help you to load the pdf on the screen.
import 'package:native_pdf_view/native_pdf_view.dart';
Widget pdfView() => FutureBuilder<PDFDocument>(
// Open document
future: PDFDocument.openAsset('assets/sample.pdf'),
builder: (_, snapshot) {
if (snapshot.hasData) {
// Show document
return PDFView(document: snapshot.data);
}
if (snapshot.hasError) {
// Catch
return Center(
child: Text(
'PDF Rendering does not '
'support on the system of this version',
),
);
}
return Center(child: CircularProgressIndicator());
},
);
To print the pdf file, use this package.
await FlutterPdfPrinter.printFile(file.path);
Here you can find a sample.
final Uint8List bytes = await pdf.save();
Printer? pri = await Printing.pickPrinter(context: context);
await Printing.directPrintPdf(
printer: pri!, onLayout: (PdfPageFormat format) async => bytes);
With this code you can view your printer and print the document for this i use
printing 5.9.3
Related
I was creating a pdf generator following guidelines from this website "https://www.wix.com/velo/forum/coding-with-velo/pdf-generator-api-npm-demo"
code screenshot
I copy every code from the guideline, but when I click the submit button, error of [data:application/pdf;base64,undefined] occur, and no record is saved at the pdf generator.
Check the link of the website here: website link
I believe it should be something wrong with the code below
//code start
import { pdf } from 'backend/pdf.jsw';
$w.onReady(function () {
var base64;
$w('#btnSubmit').onClick(() => {
let name = $w('#inName').value;
let detail = $w('#inDetail').value;
pdf(name, detail).then( e => {
base64 = e;
base64 = 'data:application/pdf;base64,' + base64
let msg = {
"conv": true,
"dataUrl": base64
}
$w('#html1').postMessage(msg);
});
});
});
// Code end
I search through the internet and some mentioned open data URl directly function is not supported since 2020 (see website). I am new in programme or codes, it would be greatful if someone could provide me the adjusted code.
Sorry for the trouble
Using Adobe PDF Embed API, you can register a callback:
this.adobeDCView = new window.AdobeDC.View(config);
this.adobeDCView.registerCallback(
window.AdobeDC.View.Enum.CallbackType.SAVE_API, (metaData, content, options) => {
})
Content is according to the docs here: https://www.adobe.io/apis/documentcloud/dcsdk/docs.html?view=view
content: The ArrayBuffer of file content
When I debug this content using chrome inspector, it shows me that content is a Int8Array.
Normally when we upload a pdf file, the user selects a file and we read as dataURI and get base64 and push that to AWS. So I need to convert this PDF's data (Int8Array) to Base64, so I can also push it to AWS.
Everything I have found online uses UInt8Array to base64, and I don't understand how to go from Int8Array to UInt8Array. I would think you can just add 128 to the signed int to get a ratio between 0-256, but this doesn't seem to work.
I have tried using this:
let decoder = new TextDecoder('utf8');
let b64 = btoa(decoder.decode(content));
console.log(b64);
But I get this error:
ERROR DOMException: Failed to execute 'btoa' on 'Window': The string to be encoded contains characters outside of the Latin1 range.
Please help me figure out how to go from Int8Array to Base64.
I use the function in this answer.
For Embed API, use the "content" parameter from the save callback as the input to the function.
You can see a working example at this CodePen. The functional part is below.
adobeDCView.registerCallback(
AdobeDC.View.Enum.CallbackType.SAVE_API,
function (metaData, content, options) {
/* Add your custom save implementation here...and based on that resolve or reject response in given format */
var base64PDF = arrayBufferToBase64(content);
var fileURL = "data:application/pdf;base64," + base64PDF;
$("#submitButton").attr("href", fileURL);
/* End save code */
return new Promise((resolve, reject) => {
resolve({
code: AdobeDC.View.Enum.ApiResponseCode.SUCCESS,
data: {
/* Updated file metadata after successful save operation */
metaData: { fileName: urlToPDF.split("/").slice(-1)[0] }
}
});
});
},
saveOptions
);
I have a Parse Cloud afterSave trigger from where I can access the obj and inside the obj a field that has a store parse file img.
I want to use sharp to resize it and save it in another field but I'm struggling and getting an error when I use sharp. Here is a summary of the code I already have inside the cloud trigger:
let file = obj.get("photo");
sharp(file)
.resize(250, 250)
.then((data) => {
console.log("img-----", data);
})
.catch((err) => {
console.log("--Error--", err);
});
After some research, I managed to figure out how to create Parse Cloud afterSave trigger which resizes and then saves the img, I couldn't find much information on it so ill post my solution so others can use it if it's helpful.
Parse.Cloud.afterSave("Landmarks", async (req) => {
const obj = req.object;
const objOriginal = req.original;
const file = obj.get("photo");
const condition = file && !file.equals(objOriginal.get("photo"));
if (condition) {
Parse.Cloud.httpRequest({ url: file.url() })
.then((res) => {
sharp(res.buffer)
.resize(250, 250, {
fit: "fill",
})
.toBuffer()
.then(async (dataBuffer) => {
const data = { base64: dataBuffer.toString("base64") };
const parseFile = new Parse.File(
"photo_thumbnail",
data
);
await parseFile.save();
await obj.save({ photo_thumb: parseFile });
})
.catch((err) => {
console.log("--Sharp-Error--", err);
});
})
.catch((err) => {
console.log("--HTTP-Request-Error--", err);
});
} else {
console.log("--Photo was deleted or did not change--");
}
});
So to break this down a bit, what i did first was get the obj and the objOriginal so i can compare them and check for a change in a specific field. This condition is necessery since in my case i wanted to save the resized img in parse which would cause an infinite loop otherwise.
After that i did a Parse.Cloud.httpRequest({ url: file.url()}).then() which is the way i found to get the buffer from the photo. The buffer is stored inside res.buffer and we need it for sharp.
Next i use sharp(res.buffer) since sharp also accepts buffers and resize it to the desired dimensions (i used the fit config for it). Then we turn the resulted img into another buffer using .toBuffer(). Furthermore, i use a .then().catch() blocks and if sharp is succesful i turned the outputed buffer into a base64 and passed it in Parse.File(), note that the specific syntax { base64: 'insert buffer here' } is important.
And finally i just save the file and the obj. Is this the best way to do it, absolytely not, but its the one i found that works. Another possible solution is instead of using buffers and base64 is to create a temporary dir which you save the images there, use them and then delete the directory. I tried this as well but had issues making it work.
This one I've been banging my head against for a few weeks now.
Scenario:
Let user generate an image out of layers they select
Convert image to canvas
Share image from canvas on facebook wall using share_open_graph (along with the image, a short text and title will be shared)
I've already had a solution in place using publish_actions but that was recently removed from the API and is no longer available.
I am using js and html for all code handling.
The issue is that I can generate a png image from the canvas but that is saved as base64 and share_open_graph doesn't allow this type of image, it needs a straight forward url such as './example.png'. I have tried using several approaches and with canvas2image, converting and saving image using file-system but all of these fail.
Does anyone have similar scenario and possible solution from April/May 2018 using share_open_graph ?
My current code looks like this - it fails at the image conversion and save to a file (Uncaught (in promise) TypeError: r.existsSync is not a function at n (file-system.js:30)). But I am open to different solutions as this is clearly not working.
html2canvas(original, { width: 1200, height: 628
}).then(function(canvas)
{
fb_image(canvas);
});
var fb_image = function(canvas) {
canvas.setAttribute('id', 'canvas-to-share');
document.getElementById('img-to-share').append(canvas);
fbGenerate.style.display = 'none';
fbPost.style.display = 'block';
var canvas = document.getElementById('canvas-to-share');
var data = canvas.toDataURL('image/png');
var encodedPng = data.substring(data.indexOf(',') + 1, data.length);
var decodedPng = base64.decode(encodedPng);
const buffer = new Buffer(data.split(/,\s*/)[1], 'base64');
pngToJpeg({ quality: 90 })(buffer).then(output =>
fs.writeFile('./image-to-fb.jpeg', output));
var infoText_content = document.createTextNode('Your image is being
posted to facebook...');
infoText.appendChild(infoText_content);
// Posting png from imageToShare to facebook
fbPost.addEventListener('click', function(eve) {
FB.ui(
{
method: 'share_open_graph',
action_type: 'og.shares',
href: 'https:example.com',
action_properties: JSON.stringify({
object: {
'og:url': 'https://example.com',
'og:title': 'My shared image',
'og:description': 'Hey I am sharing on fb!',
'og:image': './image-to-fb.jpeg',
},
}),
},
function(response) {
console.log(response);
}
);
});
};
I'm working on a react native iOS app where I want to take certain images from a user's Camera Roll and save them in cloud storage (right now I'm using Firebase).
I'm currently getting the images off the Camera Roll and in order to save each image to the cloud I'm converting each image uri to base64 and then to a blob using the react-native-fetch-blob library. While this is working I am finding the conversion process to base64 for each image to be taking a very long time.
An example image from the Camera Roll:
What would be the most efficient/quickest way to take the image uri for each image from the Camera Roll, convert it, and store it to cloud storage.
Is there a better way I can be handling this? Would using Web Workers speed up the base64 conversion process?
My current image conversion process:
import RNFetchBlob from 'react-native-fetch-blob';
const Blob = RNFetchBlob.polyfill.Blob;
const fs = RNFetchBlob.fs
window.XMLHttpRequest = RNFetchBlob.polyfill.XMLHttpRequest
window.Blob = Blob
function saveImages(images) {
let blobs = await Promise.all(images.map(async asset => {
let response = await convertImageToBlob(asset.node.image.uri);
return response;
}));
// I will then send the array of blobs to Firebase storage
}
function convertImageToBlob(uri, mime = 'image/jpg') {
const uploadUri = uri.replace('file://', '');
return new Promise(async (resolve, reject) => {
let data = await readStream(uploadUri);
let blob = await Blob.build(data, { type: `${mime};BASE64` });
resolve(blob);
})
}
function readStream(uri) {
return new Promise(async (resolve, reject) => {
let response = await fs.readFile(uri, 'base64');
resolve(response);
})
}
I found the solution below to be extremely helpful in speeding up the process. The base64 conversion now takes place on the native side rather than through JS.
React Native: Creating a custom module to upload camera roll images.
It's also worth noting this will convert the image to thumbnail resolution.
To convert an image to full resolution follow guillaumepiot's solution here:
https://github.com/scottdixon/react-native-upload-from-camera-roll/issues/1
I would follow the example here form the react-native-fetch docs. It looks like you're trying to add an extra step when they take care of that for you.
https://github.com/wkh237/react-native-fetch-blob#upload-a-file-from-storage