Flying-saucer/iText PDF not finding css file - css

I can generate a PDF using flying-saucer/iText. However, I can't figure out how to get the style sheet included in the PDF rendering.
I have used this flying-saucer/iText PDF in servlet not finding css file as reference.
There are multiple css files involved so I won't be able to use renderer.setDocument(doc, "http://example.com/something/page.html");
as a solution
I have implemented a something similar to what the asker used, but it's returning a Caused by: java.nio.file.InvalidPathException: Illegal char <:> at index 4: http://localhost:8080/proj/resources/css/custom1.css error
Here is my code
StringBuilder bui = new StringBuilder();
bui.append("<html><head><style>");
bui.append(readFile(path+"/resources/css/custom1.css", Charsets.UTF_8));
bui.append(readFile(path+"/resources/css/custom2.css", Charsets.UTF_8));
bui.append(readFile(path+"/resources/css/custom3.css", Charsets.UTF_8));
bui.append("</style></head>");
bui.append("<body><div><table>");
bui.append( xhtml_file );
bui.append("</table></div></body></html>");
InputStream stream = new ByteArrayInputStream(bui.toString().getBytes( StandardCharsets.UTF_8 ));
Document doc = tidy.parseDOM(stream, null);
File outputFile = new File(directory+ "FILENAME" +".pdf");
os = new FileOutputStream(outputFile);
ITextRenderer renderer = new ITextRenderer();
renderer.setDocument(doc, null);
renderer.layout();
renderer.createPDF(os, false);
renderer.finishPDF();
the path being passed is "http://localhost:8080"
if I enter "http://localhost:8080/resources/css/custom1.css" directly into the address bar, it shows the css file. I tried removing the 'path' but it's also not getting the css. What am I doing wrong?

Try the file:/// url protocol to point (with three slashes) pointing to the css file directly.

Related

Save an Image with a new file name [ImageSharp]

I have upgraded my project from .net framework to .net 6 (core). In my project, there are many places where Bitmap is used. I have read in the microsoft documentations that System.Drawing.Common will only support the Windows platform and even after adding the EnableUnixSupport configuration, it will not be supported in net7.So, now I am using ImageSharp.Web. I have the scenario where I save a file as Image (the format is .tiff) then I read from that path as bitmap and save as PNG ( due to some business rule)
Following is the line of code I am trying change:
Bitmap.FromFile(completePath).Save(pngPath, ImageFormat.Png);
This is the code I have converted into. The only issue is how to save as a new file name as the Tiff file has tiff in the file name.
string extension = _GetExtension(img.ContentType);
if (extension == Constants.TiffExtension)
{
fileName = fileName.Replace(Constants.TiffExtension, "PNG");
using (var outputStream = new FileStream(completePath, FileMode.CreateNew))
{
var image = SixLabors.ImageSharp.Image.Load(completePath);
image.SaveAsync(outputStream, new PngEncoder()); //how to save new file name?
}
}
You can use the image.Save(fileName); overload to save a image to a file. The file name overload that takes just a path will automatically choose the correct encoder based on the file extension.
I was using the ImageSharp.Web package while the one I needed was the basic ImageSharp package. Special thanks to #James South for correcting me and #tocsoft for the guidance.
I have fixed it by the following code which is working:
if (extension == Constants.Conversion.TiffExtension)
{
using (SixLabors.ImageSharp.Image image = SixLabors.ImageSharp.Image.Load(completePath))
{
string pngPath = completePath.Replace(Constants.Conversion.TiffExtension, Conversion.DefaultExtension);
image.Save(pngPath);
fileName = fileName.Replace(Constants.Conversion.TiffExtension, Conversion.DefaultExtension);
}
}

What is the path of the Json file in Android at Xamarin.Forms?

I am developing an application for Android using Xamarin.
I have created a JsonData folder in the Android project and created a Setting.json file.
\MyApp\MyApp.Android\JsonData\Setting.json
In the properties, we set the Copy when new.
The following folders in the local environment contain the files.
\MyApp\MyApp.Android\bin\Debug\JsonData\Setting.json
I want to load this file in the actual Android device.
When I do this, it tells me that the file is missing.
Could not find a part of the path "/JsonData/Setting.json."
Try
{
var text = File.ReadAllText("JsonData/Setting.json", Encoding.UTF8);
var setting = JsonConvert.DeserializeObject<Setting>(text);
}
catch(Exception exception)
{
var error = exception.Message;
}
What is the path of the file in Android?
I think you're using File Handling in Xamarin.Forms incorrectly.
From the parameter of function File.ReadAllText, the app will access the file system to getSetting.json from folder JsonData in your android device.
The path of the file on each platform can be determined from a .NET Standard library by using a value of the Environment.SpecialFolder enumeration as the first argument to the Environment.GetFolderPath method. This can then be combined with a filename with the Path.Combine method:
string fileName = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), "temp.txt");
And you can read the file by code:
string text = File.ReadAllText(fileName);
In addition, from your code,I guess you want to Load your Embedded file( Setting.json) as Resources,right?
In this case,we should make sure the Build Action of your Setting.json is Embedded Resource.
And GetManifestResourceStream is used to access the embedded file using its Resource ID.
You can refer to the following code:
var assembly = IntrospectionExtensions.GetTypeInfo(typeof(LoadResourceText)).Assembly;
Stream stream = assembly.GetManifestResourceStream("YourAppName.JsonData.Setting.json");
string text = "";
using (var reader = new System.IO.StreamReader (stream))
{
text = reader.ReadToEnd ();
}
For more , you can check document : File Handling in Xamarin.Forms.
And you can also check the sample code here: https://learn.microsoft.com/en-us/samples/xamarin/xamarin-forms-samples/workingwithfiles/ .

BitmapFactory.decodeStream returns null reading local file

A quick summary of my problem: I am trying to read a local image file. If I include the file in my assets directory and treat it as an asset everything works fine. However, if I try to read it from the external sd card, BitmapFactory.decode stream returns null.
I've had the same results with both .jpeg and .png files.
This is how I obtain an InputStream from the asset file:
InputStream isa = context.getAssets().open("Boulder.jpg");
This is how I obtain an InputStream from the asset file:
File f = new File( "/mnt/extSdCard/Maps/Colorado/Boulder.jpg" );
InputStream isf = new BufferedInputStream( new FileInputStream( f.toString() ) );
In either case the InputStream is passed to this code: (If this code looks familiar, it was borrowed from an internet example)
this.decoder = BitmapRegionDecoder.newInstance(inputStream, false);
tmpOptions.inJustDecodeBounds = true;
Bitmap temp = BitmapFactory.decodeStream(inputStream, null, tmpOptions);
setSceneSize(tmpOptions.outWidth, tmpOptions.outHeight);
tmpOptions.inJustDecodeBounds = false;
tmpOptions.inSampleSize = (1<<downShift);
sampleBitmap = BitmapFactory.decodeStream(inputStream, null, tmpOptions);
Again, using the asset file derived InputStream, everything works fine. Conversely, with the sdCard file, outWidth and outHeight are both -1 after the first call and sampleBitmap is null after the second.
I'm really wrapped around the axle on with this problem and have spent a lot of time browsing this forum and experimenting with suggested solutions all to no avail. I also wrote some test code which opened both versions of the file, creating InputStreams as shown above, then read the contents of each stream and compared each byte and found them to be identical.
I've tried the code on different devices with the same results. I'm currently testing on a Galaxy Note II (Android 4.1.1) with the following version info in the AndroidManifest:
<uses-sdk android:minSdkVersion="16" android:targetSdkVersion="16"/>
I need the ability to dynamically add files to the system so including everything as an asset is not an option. Any help would be greatly appreciated.
You can simple use
BitmapFactory.decodeFile(file.getAbsolutePath(), tmpOptions);
rather than
File f = new File( "/mnt/extSdCard/Maps/Colorado/Boulder.jpg" );
InputStream isf = new BufferedInputStream( new FileInputStream( f.toString() ) );
BitmapFactory.decodeStream(inputStream, null, tmpOptions)

PDFizer: how to inset picture in generated pdf document?

i'm using PDFizer library for .NET from here - PDFizer
and i need help... how i can convert all html document(including pictures stored in it) to PDF with this library? Now i can only generate pdf without images...
After some testing, this is what you need to do:
Create a Folder in which you will have all of your Images.
If you already have an instance of Pdfizer.HtmlToPdfConverter change the ImagePath Attribute to point to the folder where your images reside.
Include the <img> tags in your html code.
Make sure the images are in the folder.
Note: I tried adding Png files and got a conversion error. Here is an example I took from the site you provided, plus my modifications:
System.Text.StringBuilder sbHtml = new System.Text.StringBuilder();
sbHtml.Append("<html>");
sbHtml.Append("<body>");
sbHtml.Append("<font size='14'>My Document Title Line</font>");
sbHtml.Append("<img src='trollface.jpg' />");
sbHtml.Append("<br />");
sbHtml.Append("This is my document text");
sbHtml.Append("</body>");
sbHtml.Append("</html>");
//create file stream to PDF file to write to
using (System.IO.Stream stream = new System.IO.FileStream
(sPathToWritePdfTo, System.IO.FileMode.OpenOrCreate))
{
// create new instance of Pdfizer
Pdfizer.HtmlToPdfConverter htmlToPdf = new Pdfizer.HtmlToPdfConverter();
// open stream to write Pdf to to
htmlToPdf.Open(stream);
htmlToPdf.ImagePath = Server.MapPath(ResolveUrl("~/Images"));
// write the HTML to the component
htmlToPdf.Run(sbHtml.ToString());
// close the write operation and complete the PDF file
htmlToPdf.Close();
}
}
Good luck!

Why does Image.FromFile keep a file handle open sometimes?

I am doing a lot of image processing in GDI+ in .NET in an ASP.NET application.
I frequently find that Image.FromFile() is keeping a file handle open.
Why is this? What is the best way to open an image without the file handle being retained.
NB: I'm not doing anything stupid like keeping the Image object lying around - and even if I was I woudlnt expect the file handle to be kept active
I went through the same journey as a few other posters on this thread. Things I noted:
Using Image.FromFile does seem unpredictable on when it releases the file handle. Calling the Image.Dispose() did not release the file handle in all cases.
Using a FileStream and the Image.FromStream method works, and releases the handle on the file if you call Dispose() on the FileStream or wrap the whole thing in a Using {} statement as recommended by Kris. However if you then attempt to save the Image object to a stream, the Image.Save method throws an exception "A generic error occured in GDI+". Presumably something in the Save method wants to know about the originating file.
Steven's approach worked for me. I was able to delete the originating file with the Image object in memory. I was also able to save the Image to both a stream and a file (I needed to do both of these things). I was also able to save to a file with the same name as the originating file, something that is documented as not possible if you use the Image.FromFile method (I find this weird since surely this is the most likely use case, but hey.)
So to summarise, open your Image like this:
Image img = Image.FromStream(new MemoryStream(File.ReadAllBytes(path)));
You are then free to manipulate it (and the originating file) as you see fit.
I have had the same problem and resorted to reading the file using
return Image.FromStream(new MemoryStream(File.ReadAllBytes(fileName)));
Image.FromFile keeps the file handle open until the image is disposed. From the MSDN:
"The file remains locked until the Image is disposed."
Use Image.FromStream, and you won't have the problem.
using(var fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
{
return Image.FromStream(fs);
}
Edit: (a year and a bit later)
The above code is dangerous as it is unpredictable, at some point in time (after closing the filestream) you may get the dreaded "A generic error occurred in GDI+". I would amend it to:
Image tmpImage;
Bitmap returnImage;
using(var fs = new FileStream(filename, FileMode.Open, FileAccess.Read))
{
tmpImage = Image.FromStream(fs);
returnImage = new Bitmap(tmpImage);
tmpImage.Dispose();
}
return returnImage;
Make sure you are Disposing properly.
using (Image.FromFile("path")) {}
The using expression is shorthand for
IDisposable obj;
try { }
finally
{
obj.Dispose();
}
#Rex in the case of Image.Dispose it calls GdipDisposeImage extern / native Win32 call in it's Dispose().
IDisposable is used as a mechanism to free unmanaged resources (Which file handles are)
I also tried all your tips (ReadAllBytes, FileStream=>FromStream=>newBitmap() to make a copy, etc.) and they all worked. However, I wondered, if you could find something shorter, and
using (Image temp = Image.FromFile(path))
{
return new Bitmap(temp);
}
appears to work, too, as it disposes the file handle as well as the original Image-object and creates a new Bitmap-object, that is independent from the original file and therefore can be saved to a stream or file without errors.
I would have to point my finger at the Garbage Collector. Leaving it around is not really the issue if you are at the mercy of Garbage Collection.
This guy had a similar complaint... and he found a workaround of using a FileStream object rather than loading directly from the file.
public static Image LoadImageFromFile(string fileName)
{
Image theImage = null;
fileStream = new FileStream(fileName, FileMode.Open, FileAccess.Read);
{
byte[] img;
img = new byte[fileStream.Length];
fileStream.Read(img, 0, img.Length);
fileStream.Close();
theImage = Image.FromStream(new MemoryStream(img));
img = null;
}
...
It seems like a complete hack...
As mentioned above the Microsoft work around causes a GDI+ error after several images have been loaded. The VB solution for me as mentioned above by Steven is
picTemp.Image = Image.FromStream(New System.IO.MemoryStream(My.Computer.FileSystem.ReadAllBytes(strFl)))
I just encountered the same problem, where I was trying to merge multiple, single-page TIFF files into one multipart TIFF image. I needed to use Image.Save() and 'Image.SaveAdd()`: https://msdn.microsoft.com/en-us/library/windows/desktop/ms533839%28v=vs.85%29.aspx
The solution in my case was to call ".Dispose()" for each of the images, as soon as I was done with them:
' Iterate through each single-page source .tiff file
Dim initialTiff As System.Drawing.Image = Nothing
For Each filePath As String In srcFilePaths
Using fs As System.IO.FileStream = File.Open(filePath, FileMode.Open, FileAccess.Read)
If initialTiff Is Nothing Then
' ... Save 1st page of multi-part .TIFF
initialTiff = Image.FromStream(fs)
encoderParams.Param(0) = New EncoderParameter(Encoder.Compression, EncoderValue.CompressionCCITT4)
encoderParams.Param(1) = New EncoderParameter(Encoder.SaveFlag, EncoderValue.MultiFrame)
initialTiff.Save(outputFilePath, encoderInfo, encoderParams)
Else
' ... Save subsequent pages
Dim newTiff As System.Drawing.Image = Image.FromStream(fs)
encoderParams = New EncoderParameters(2)
encoderParams.Param(0) = New EncoderParameter(Encoder.Compression, EncoderValue.CompressionCCITT4)
encoderParams.Param(1) = New EncoderParameter(Encoder.SaveFlag, EncoderValue.FrameDimensionPage)
initialTiff.SaveAdd(newTiff, encoderParams)
newTiff.Dispose()
End If
End Using
Next
' Make sure to close the file
initialTiff.Dispose()

Resources