We have a workflow where we are receiving employee documents back from a 3rd party service in a PDF byte array. How would we go about converting this byte array to a PDF to store into Laserfiche?
Question
Question
Answer
Something like this should work but I didn't have much time to test it:
string token = this.WorkflowApi.GetTokenValueFromNameAsString("HTTPWebRequest_Content File", 1); string base64PDF = null; using(StringReader stringReader = new StringReader(token)) { using(XmlReader reader = XmlReader.Create(stringReader)) { if(!reader.ReadToFollowing("GetFormAsPDF")) { this.WorkflowApi.TrackWarning("HTTP Response was not valid."); return; } base64PDF = reader.Value; } } this.SetTokenValue("Base64PDF", base64PDF); byte[] pdfBytes = Convert.FromBase64String(base64PDF); DocumentInfo doc = this.BoundEntryInfo as DocumentInfo; if (doc == null) { this.WorkflowApi.TrackWarning("Entry was not a document."); return; } using (Stream edocStream = doc.WriteEdoc("application/pdf", pdfBytes.Length)) { edocStream.Write(pdfBytes, 0, 0); } doc.Extension = ".pdf"; doc.Save();
Replies
Are you using the Http Request Activity? If so you can use the Attach E-doc activity if the web service is returning the PDF document as the response.
We are using the HTTP Request activity. We will give it a try. Thank you!
So if my Web Request reply looks like this:
<?xml version="1.0" encoding="utf-8" standalone="yes"?> <GetFormAsPDF p1:type="Edm.Binary" xmlns:p1="http://schemas.microsoft.com/ado/2007/08/dataservices/metadata" xmlns="http://schemas.microsoft.com/ado/2007/08/dataservices">JVBERi0xLjANCjEgMCBvYmoNCjw8DQovVHlwZSAvQ2F0YWxvZw0KL1BhZ2VzIDMgMCBSDQovT3V0bGluZXMgMiAwIFINCi9QYWdlTW9kZSAvVXNlT3V0bGluZXMNCi9QYWdlTGF5b3V0IC9PbmVDb2x1bW4NCj4+DQplbmRvYmoNCiUlIEZvckFwcE5vJSUgVGl0bGVTdHJpbmc6IEhlYWx0aCBJbnN1cmFuY2UgTWFya2V0IFBsYWNlIENvdmVyYWdlIC==</GetFormAsPDF>
Do I need to extract just the data in between the GetFormAsPDF tags?
You have to extract the string and decode it from Base 64.
Unfortunately that is outside what Attach e-doc can support at this time.
You'll want to use a script and the Convert.FromBase64String function to get a byte[] that you put into your e-doc stream.
Has anyone created a script like what Ed is referring to that would be willing to share their work?
Something like this should work but I didn't have much time to test it:
string token = this.WorkflowApi.GetTokenValueFromNameAsString("HTTPWebRequest_Content File", 1); string base64PDF = null; using(StringReader stringReader = new StringReader(token)) { using(XmlReader reader = XmlReader.Create(stringReader)) { if(!reader.ReadToFollowing("GetFormAsPDF")) { this.WorkflowApi.TrackWarning("HTTP Response was not valid."); return; } base64PDF = reader.Value; } } this.SetTokenValue("Base64PDF", base64PDF); byte[] pdfBytes = Convert.FromBase64String(base64PDF); DocumentInfo doc = this.BoundEntryInfo as DocumentInfo; if (doc == null) { this.WorkflowApi.TrackWarning("Entry was not a document."); return; } using (Stream edocStream = doc.WriteEdoc("application/pdf", pdfBytes.Length)) { edocStream.Write(pdfBytes, 0, 0); } doc.Extension = ".pdf"; doc.Save();
Ed, so would I do something like the following:
When I try to tell the Attach PDF Form activity to Attach a file from the "EForm to PDF Request from Applitrack" activity, the script is not available to select from. How would I accomplish that?
You shouldn't need the attach pdf form activity in this sample since the script is doing that work already.
Ed, when I try add the Script activity and then add what you posted into the Script Editor where it says 'Write your code here, it gives me a bunch of errors when I hover over the exclamation point. Am I supposed to be entering what you posted a different way into the script activity?
Also, how to I do I tell the script to process the byte array that is returned from the "EForm to PDF Request from Applitrack" activity? Here is a screenshot of what I have currently:
What do the errors say? Stuff like "'String' is a class type and cannot be used as an expression."?
Ed's code was in C#, your activity seems to be using VB.NET.
I switched it to C# and that seems to have gotten rid of some of the error messages, but now I am seeing things like "namespace stringready could not be found" or "namespace xmlreader could not be found".
Add a reference to System.IO to your script. Then at the top in the using statements, add
using System.IO; using System.Xml;
That got rid of most of the errors. I now have 3 left.
The script above assumes WF 9.1.1. Are you running 9.0.2 or lower?
No, we are running the latest version of 9.2.
We got the errors figured out. We were not using the SDK script activity. A couple of other questions on this though. Does the script attach the PDF to the entry created in the "Create Entry" step of the workflow or do I need to change something for that to happen?
Lines 27-33 save the PDF to the Laserfiche doc.
The code that Ed provided will import the PDF into the Document Entry you set the Script activity to run against. You can see that on line 20:
DocumentInfo doc = this.BoundEntryInfo as DocumentInfo;
Thanks Bert!
The code from @ed heaney didn't work out of the box but was very helpful in helping to create the pdf. Here is his modified code that works for me.
The scenario is you are submitting a base64 string using the Rest web api RestWorkflowAPI.svc by calling a workflow. The workflow in its simplest form just has the 1. Create entry and 2. SDK Script. The SDK Script is bound to the output of the Create entry which creates the blank pdf file. The script then will write to that file.
I am not sure why he was reading the base64 string with the xml reader. If I am missing something, let me know. In any case, this was tested and works.
protected override void Execute() { //pdffile is a param written from the webserver with the pdf string string token = this.WorkflowApi.GetTokenValueFromNameAsString("pdffile", 1); //converts back to bytes byte[] pdfBytes = Convert.FromBase64String(token); //grab the create entry DocumentInfo doc = this.BoundEntryInfo as DocumentInfo; if (doc == null) { this.WorkflowApi.TrackWarning("Entry was not a document."); return; } //write to the output entry of the created entry using (Stream edocStream = doc.WriteEdoc("application/pdf", pdfBytes.Length)) { edocStream.Write(pdfBytes, 0, pdfBytes.Length); //changed 0 to pdfBytes.Length } doc.Extension = ".pdf"; doc.Save(); }
Anyway to write the bytes of an image to a native page? There seems to be no reference in Workflow for this kind of stuff. Just a list of functions.
Have you just tried changing the "applicant/pdf" to something like "applicant/tiff" or "applicant/jpg", whatever the convention is?
Then also change the extension from ".pdf" to the corresponding file extension.
So long as the image was converted from string to byte array after it gets passed through, it should work. I think...but have not tested.
First I tried changing doc.WriteEdoc to doc.WriteNdoc and the function did not exist. I can't write to an electronic document when I am trying to create a native document.
This is where I get confused, how did anyone figure all this out? Is there a guide somewhere I should be checking out?
Chad,
You can't use document-level methods like doc.WriteEdoc because each page is a separate object and has to be updated directly.
First, create the page where you want the image to go, then use the PageInfo.WritePagePart() method to add your image.
This method accepts a byte array.
For example, something like this:
PageInfo newPage = doc.AppendPage(); using (Stream writer = newPage.WritePagePart(PagePart.Image, bytes.Length){ writer.Write(bytes, 0, bytes.Length); } newPage.Save();
Thank you! I thought it might be a whole different method but I can't seem to find any examples in the SDK Script activity. This is what I was looking for though!
Hey Ed,
Could you give some more insight on how this script should be written? We have limited knowledge in this process and any help would be appreciated!
Thanks!
Thank you everyone for the help. Below is the completed Workflow we came up with for our needs based on the feedback here:
And below are the contents of the SDK Script:
namespace WorkflowActivity.Scripting.SDKScript { using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Data.SqlClient; using System.Text; using System.IO; using System.Xml; using Laserfiche.RepositoryAccess; /// <summary> /// Provides one or more methods that can be run when the workflow scripting activity is performed. /// </summary> public class Script1 : RAScriptClass92 { /// <summary> /// This method is run when the activity is performed. /// </summary> protected override void Execute() { string token = this.WorkflowApi.GetTokenValueFromNameAsString("EFormtoPDFRequestfromApplitrack_Content", 0); //var token2 = GetTokenValue("EFormtoPDFRequestfromApplitrack_Content File"); // string token = this.WorkflowApi.GetTokenValueFromNameAsString("HTTPWebRequest_Content File", 1); string base64PDF = null; using(StringReader stringReader = new StringReader(token)) { using(XmlReader reader = XmlReader.Create(stringReader)) { if(!reader.ReadToFollowing("GetFormAsPDF")) { this.WorkflowApi.TrackWarning("HTTP Response was not valid."); return; } base64PDF = reader.ReadElementContentAsString("GetFormAsPDF", "http://schemas.microsoft.com/ado/2007/08/dataservices"); } } this.SetTokenValue("Base64PDF", base64PDF); byte[] pdfBytes = Convert.FromBase64String(base64PDF); DocumentInfo doc = this.BoundEntryInfo as DocumentInfo; if (doc == null) { this.WorkflowApi.TrackWarning("Entry was not a document."); return; } using (Stream edocStream = doc.WriteEdoc("application/pdf", pdfBytes.Length)) { edocStream.Write(pdfBytes, 0, pdfBytes.Length); } doc.Extension = ".pdf"; doc.Save(); } } }
I hope it helps someone.
Dear Blake, Could you give me support with this suggested solution for importing documents in Laserfiche, I've been having problems for several days without finding a solution to this requirement. I appreciate your support, I don't know if we can get in touch, my phone number is +51947285904 A lot of thanks.
Hey Ed pleaseeee,
Could you give some more insight on how this script should be written? We have limited knowledge in this process and any help would be appreciated!
I have for import a document (format: jpg, pdf) and i dont know step by step how Do this process.
Thanks a lot!
Good Morning, In my case I have an external url in which the document will be received within the parameters (blob format files), could you explain to me a guide on how I could do to achieve the objective of registering this information in the laserfiche database please, in Laserfiche API Cloud?
You should make the script a C# script, it looks like in the workflow you have it set to a visual basic script.That's assuming you copied ed's code which is C#.
Edit - didn't see the reply that pointed this out, disregard.
Hii all ,
we are reading a PDF File in byte array format through HTTP Web Service in our Workflow.
Aspx .
We need to retrieve the PDF Contents now through our SDK Script.
How can we do the same?? Thanks for your help.
namespace WorkflowActivity.Scripting.SDKScript { using System; using System.Collections.Generic; using System.ComponentModel; using System.Data; using System.Data.SqlClient; using System.Text; using System.IO; using System.Xml; using Laserfiche.RepositoryAccess; /// <summary> /// Provides one or more methods that can be run when the workflow scripting activity is performed. /// </summary> public class Script1 : RAScriptClass92 { /// <summary> /// This method is run when the activity is performed. /// </summary> protected override void Execute() { string token = this.WorkflowApi.GetTokenValueFromNameAsString("EFormtoPDFRequestfromApplitrack_Content", 0); //var token2 = GetTokenValue("EFormtoPDFRequestfromApplitrack_Content File"); // string token = this.WorkflowApi.GetTokenValueFromNameAsString("HTTPWebRequest_Content File", 1); string base64PDF = null; using(StringReader stringReader = new StringReader(token)) { using(XmlReader reader = XmlReader.Create(stringReader)) { if(!reader.ReadToFollowing("GetFormAsPDF")) { this.WorkflowApi.TrackWarning("HTTP Response was not valid."); return; } base64PDF = reader.ReadElementContentAsString("GetFormAsPDF", "http://schemas.microsoft.com/ado/2007/08/dataservices"); } } this.SetTokenValue("Base64PDF", base64PDF); byte[] pdfBytes = Convert.FromBase64String(base64PDF); DocumentInfo doc = this.BoundEntryInfo as DocumentInfo; if (doc == null) { this.WorkflowApi.TrackWarning("Entry was not a document."); return; } using (Stream edocStream = doc.WriteEdoc("application/pdf", pdfBytes.Length)) { edocStream.Write(pdfBytes, 0, pdfBytes.Length); } doc.Extension = ".pdf"; doc.Save(); } } }
To send data across the web, it needs to be converted to a string. You will notice in the code sample provided by Ed that he is loading the received data into a string object and then generating a byte array using Convert.FromBase64String:
string base64PDF = null; ... byte[] pdfBytes = Convert.FromBase64String(base64PDF);
So in your code to send the PDF, you must convert your byte array into a Base64String and then send the string to the requester.