PDF Image from Binary in MTOM - c#

I am making a custom HttpWebRequest call to a GSoap web service that returns an XML + XOP envelope which contains a PDF Image as binary.
I am grabbing the response and taking the binary code in between the boundary string.
Finally, I convert the binary to byte[] and save it as a PDF.
Now, I can see the PDF metadata so the encoding was right, but when I try to open it, I get insufficient data for an image error and the image inside the PDF is not displayed.
I am converting the binary string via this:
retBytes = System.Text.Encoding.UTF8.GetBytes(modStr);
Where modStr is the string starting with %PDF-1.1 and ending with %%EOF. Do I need to do more encoding/decoding so that the image shows up granted I can see everything else (pages/metadata, etc)?

Related

Google Drive API / GUI exports invalid PDF - not readable by iText7

I'm trying to export multiple Google Docs files via Google Drive API into Pdf and merge them into one using iText7 but it throws exception iText.IO.Exceptions.IOException: 'PDF header not found.' because of the weird PDF format from Google export.
Google Disk generated PDF content (read with notepad) is not valid PDF.
File content starts like this 倥䙄ㄭ㐮┊ㄊ instead of something like %PDF-1.4
The uploaded PDF file is readable from Google Disk without any problem and it is readable even if I export the Stream directly to the disk. File content is exactly the same when I download file manually through Google Docs GUI.
Here is my code to export files via API:
var mimeType = "application/pdf";
var file = GetFile(sourceFile);
var pdfRequest = _driveService.Files.Export(sourceFile, mimeType);
var stream = pdfRequest.ExecuteAsStream();
Then I'm uploading PDF back into Google Drive via it's API
var newFile = new Google.Apis.Drive.v3.Data.File();
newFile.MimeType = mimeType;
newFile.Parents = new List<string>() { targetFolder };
var createRequest = _driveService.Files.Create(newFile, stream, mimeType);
createRequest.SupportsAllDrives = true;
var createResult = createRequest.Upload();
Weirdly enough the format of exported PDF is ok when I use
var text = pdfRequest.Execute(); instead of pdfRequest.ExecuteAsStream (it starts with %PDF-1.7).
But Execute() returns string instead of Stream.
Is there any way to get standard PDF format from Google Disk API or convert it in any possible way?
The problem was in the iText7 itself. It considered PDF as invalid but it probably just does not support PDFs in iso8859_2 encoding.
I tried to use PDFSharp instead and everything went smoothly.
I've used ExecuteAsStream() from Google Disk API to get PDF Stream with no problems at all so it wasnt at fault.
Thanks for all your tips.

Base64.getEncoder().encode and generate PDF in C#

I am working on a project that uses a web service developed in Java. The response of this web service is a json file with a key generated with this java method (Base64.getEncoder().encode(array), where "array" is byte[]. This key is supposedly a binary to generate the pdf, but as much as I try, the pdf is not generated correctly, it cannot be opened.
Can anybody help me to generate a pdf with this response in C#?
You need to convert from Base64, to byte and then get the pdf:
Check this example:
string base64EncodedFile = // Get the string representation from the api
using (System.IO.FileStream stream = System.IO.File.Create("c:\\saved.pdf))
{
System.Byte[] byteArray = System.Convert.FromBase64String(base64EncodedFile);
stream.Write(byteArray, 0, byteArray.Length);
}
For more information check wikipedia on base 64
Base64 is a way to encode binary data into an ASCII character set
known to pretty much every computer system, in order to transmit the
data without loss or modification of the contents itself
And that is why the java service does the conversion.

InsertInlineImage or ReplaceImage URI

I'm writing a WinForms application. I created a Google Doc template file that contains placeholders like {{name}} for various text elements. I can successfully make a copy of this document and use the BatchUpdateDocumentRequest to modify them just fine.
However, I also have an embedded image in the document. I can obtain the objectId for this image just fine. I either want to replace this image with another or remove it from my template and then append my new image to the end of the document. In both cases, the InsertInlineImage or ReplaceImage classes require a URI of the image to insert or replace with. This is where I have an issue.
The image itself has been captured from a control on the WinForms. Its actually a chart. I've saved the image in PNG format since I know that is one of the formats supported by Google drive/docs. I figured in order to use it in the batch update, I would need to upload it first, so I did and got its file id and webcontentlink back in the response.
I'm not locked into any particular way of doing this. I originally tried creating an HTML file, uploading but then it would strip the image from it, so became useless, so I switched gears to using a Google Doc as my template and just try to replace elements in it instead. This went well until I got to the image.
Essentially no matter what I try to specify as the URI, it says the file in not in a supported format.
As far as I can tell, Google expects the URI to actually end in .png or be a real link versus a download URL you'd get from Google Drive.
Here is an example of the code I'm using to attempt to replace the image. The strImageObjectId is the objectId of the Embedded Object image in the template document copy that I want to replace. The Uri is what Google needs to pull the new image from. I'm happy to pull it from my local computer or Google Drive if only I could get it to accept it somehow.
BatchUpdateDocumentRequest batchUpdateRequest = new BatchUpdateDocumentRequest {
Requests = new List<Google.Apis.Docs.v1.Data.Request>()
};
request = new Google.Apis.Docs.v1.Data.Request {
ReplaceImage = new ReplaceImageRequest() {
ImageObjectId = strImageObjectId,
Uri = strChartWebContentLink
}
};
batchUpdateRequest.Requests.Add(request);
DocumentsResource.BatchUpdateRequest updateRequest =
sDocsService.Documents.BatchUpdate(batchUpdateRequest, strCopyFileId);
BatchUpdateDocumentResponse updateResponse = updateRequest.Execute();
I'm happy to use whatever method will get me to a point where I an end up with a Google Doc on Google Drive that was based on a template in which I can replace various text elements, but most importantly add/replace an image.
Thanks so much for the advice.
I got to the point were I believe I was specifying the URI correctly, but then I started getting an access forbidden error instead.
I didn't have time to hunt this one down, so I went back to creating an HTML template with my image, uploading as a Google Doc, exporting to PDF, and then uploading as a PDF. This ended up working because originally I was using a BMP as the file format and that is not supported by Google Docs, so I changed to a PNG instead and it worked just fine.
I think Google Docs needs to add the ability to add an image using a MemoryStream or some other programmatic base64 resource instead of purely being based on URIs and running into temporary upload or permission issues.
Hey I'm doing the same thing with you,
and I got this, by modify the download link format.
from this:
https://docs.google.com/uc?export=download&id={{YOUR GDRIVE IMAGE
ID}
to this
https://docs.google.com/uc?export=view&id={{YOUR GDRIVE IMAGE ID}
e.g :
uri: "https://docs.google.com/uc?export=view&id=1cjgyHqtYSgS0CBT4x-9eQIHRzOIfGgv-"
but the image should be set for public privilege

Save text with emoji to file become '?'

What I have to do
I have to create a text file (.txt, .doc, ...) with the exact text passed (so with emojis) by a .net WebaApi (and attach it to an email).
Situation:
I have a project with .net webapi. One of my routes consist of creating a text file and attach it to an email, with some text passed by a device that may contain emojis.
I can't figure out how to save emojis correctly. If I copy-paste an emoji into a word or notepad file it works, but if I save it through my code it doesn't. I suppose it is due to formatting, but I tried Unicode, UTF-32, UTF-8, ASCII,...
I tried many solutions found here on SO, but none of them worked for me.
For example this emoji (copy-pasted from .net debugger) --> 🎶 is converted into quotation mark or ¶ó, based on encoding used.
How can I save emoji as text into a file so that they can be read by the receivers?
This is what I've done:
//smsText is a string containing emojis
byte[] bytes = Encoding.Unicode.GetBytes(smsText);
Attachment attachment = new Attachment(new MemoryStream(bytes), tokenKey + ".doc");
attachment.ContentType = new ContentType("application/ms-word");
List <Attachment> attachments = new List<Attachment>();
attachments.Add(attachment);
//send email with attachments
Note that smsText, with debugger, contains the 🎶 correctly displayed.
The email correctly reach the receiver, with the .doc attachment, but the attachment doesn't contains the emojis
Your smsText contains a plaintext string. You can't just write that string into a stream or file that you then call a Word file*.
Word files are binary files with a specific format. You need to use a library that can write this format, or use Interop to interoperate with an existing Word installation.
See for example Free library to MS Word.
And if you're fine with plaintext files, just write the text's bytes to a stream and propagate the appropriate encoding (in this case Unicode, being UTF-16 on .NET).
*: yes you can, just like that Excel tries its best to format an HTML table as an Excel document, but you shouldn't.

How to display the skype user photo from HTTP Response using UCWA API?

I am working on Universal Windows Applications, in my current project I used Unified Communications Web API (UCWA) to display the skype user status it's working fine but when I am trying to display the skype user photo at that time I got stuck.
I followed below link to display the photo
https://msdn.microsoft.com/en-us/skype/ucwa/getmyphoto
I got response code of 200 OK for my GET request but I don't know how to display the image from my response.
Please tell me how to resolve it.
-Pradeep
I got Result, After getting HTTP Response then I am converting those response content to stream type by using this below line.
var presenceJsonStr = await httpResponseMessage.Content.ReadAsStreamAsync();
This is the code to display the image
var photo = await AuthenticationHelper.Photo();
// Create a .NET memory stream.
var memStream = new MemoryStream();
// Convert the stream to the memory stream, because a memory stream supports seeking.
await photo.CopyToAsync(memStream);
// Set the start position.
memStream.Position = 0;
// Create a new bitmap image.
var bitmap = new BitmapImage();
// Set the bitmap source to the stream, which is converted to a IRandomAccessStream.
bitmap.SetSource(memStream.AsRandomAccessStream());
// Set the image control source to the bitmap.
imagePreivew.ImageSource = bitmap;
Assuming you put an Accept header specifying an image type, you should be able to look at the Content-Length header to determine if the user has an image set on the server. If the length is zero you should consider providing a default image to be displayed. If not, I would suggest taking a look at Convert a Bitmapimage into a Byte Array and Vice Versa in UWP Platform as you should treat the response body as a byte array with its length defined by the Content-Length header.
If for some reason no Accept header was provided, the response body is not an image/* type, and looks like a string then you might be dealing with a Base64 encoded image. This case should be much less likely to deal with, but if you need advice I would suggest looking at Reading and Writing Base64 in the Windows Runtime.
You can directly use the URL generated for the user photo resource. Just set the URL of the image as the source of the Image container. You application would load it automatically.

Categories

Resources