Support to convert the HTML to PDF in Xamarin Forms - pdf

With the reference of following StackOverflow suggestion,
Convert HTML to PDF in .NET
I tried to convert the HTML file to PDF using HtmlRenderer.PdfSharp but unfortunately it shows compatible error like below,
HtmlRendererCore.PdfSharpCore 1.0.1 is not compatible with netstandard2.0 (.NETStandard,Version=v2.0). Package HtmlRendererCore.PdfSharpCore 1.0.1 supports: netcoreapp2.0 (.NETCoreApp,Version=v2.0)
HtmlRenderer.Core 1.5.0.5 is not compatible with monoandroid90 (MonoAndroid,Version=v9.0). Package HtmlRenderer.Core 1.5.0.5 supports:
- net20 (.NETFramework,Version=v2.0)
- net30 (.NETFramework,Version=v3.0)
- net35-client (.NETFramework,Version=v3.5,Profile=Client)
- net40-client (.NETFramework,Version=v4.0,Profile=Client)
- net45 (.NETFramework,Version=v4.5)
HtmlRendererCore.PdfSharpCore 1.0.1 is not compatible with monoandroid90 (MonoAndroid,Version=v9.0). Package HtmlRendererCore.PdfSharpCore 1.0.1 supports: netcoreapp2.0 (.NETCoreApp,Version=v2.0)
And I tried with wkhtmltopdf too but it throws similar error in android and other platform projects.
My requirement is to convert the HTML file to PDF file only (no need to view the PDF file, just to save it in local path).
Can anyone please provide suggestions?
Note : Need open source suggestion :)
Awaiting for your suggestions !!!
Support to convert the HTML to PDF in Xamarin Forms

You can read the HTML as a stream and store it into local like below,
public static class FileManager
{
public static async Task<MemoryStream> DownloadFileAsStreamAsync(string url)
{
try
{
var stream = new MemoryStream();
using (var httpClient = new HttpClient())
{
var downloadStream = await httpClient.GetStreamAsync(new Uri(url));
if (downloadStream != null)
{
await downloadStream.CopyToAsync(stream);
}
}
return stream;
}
catch (Exception exception)
{
return null;
}
}
public static async Task<bool> DownloadAndWriteIntoNewFile(string url, string fileName)
{
var stream = await DownloadFileAsStreamAsync(url);
if (stream == null || stream.Length == 0)
return false;
var filePath = GetFilePath(fileName);
if (!File.Exists(filePath))
return false;
File.Delete(filePath);
// Create file.
using (var createdFile = File.Create(filePath))
{
}
// Open and write into file.
using (var openFile = File.Open(filePath, FileMode.Open, FileAccess.ReadWrite))
{
stream.WriteTo(openFile);
}
return true;
}
public static string GetFilePath(string fileName)
{
var filePath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.LocalApplicationData), fileName);
return filePath;
}
public static void WriteAsText(string filePath, string contents)
{
File.WriteAllText(filePath, contents);
}
public static string ReadAsText(string filePath)
{
return File.ReadAllText(filePath);
}
}
You can read a stored pdf file and displayed using webview like below,
private async void HtmlToPDF()
{
await FileManager.DownloadAndWriteIntoNewFile("https://www.google.co.in/?gws_rd=ssl", "SavePDF.pdf");
var filePath = FileManager.GetFilePath("SavePDF.pdf");
var pdfString = FileManager.ReadAsText(filePath);
var webView = new WebView
{
Source = new HtmlWebViewSource
{
Html = pdfString
}
};
this.Content = webView;
}
And the output below,
Likewise, you can save HTML as PDF and do what you want..

you can use the HtmlToPdfConverter
private void ConvertUrlToPdf()
{
try {
String serverIPAddress = serverIP.Text;
uint serverPortNumber = uint.Parse (serverPort.Text);
// create the HTML to PDF converter object
HtmlToPdfConverter htmlToPdfConverter = new HtmlToPdfConverter (serverIPAddress, serverPortNumber);
// set service password if necessary
if (serverPassword.Text.Length > 0)
htmlToPdfConverter.ServicePassword = serverPassword.Text;
// set PDF page size
htmlToPdfConverter.PdfDocumentOptions.PdfPageSize = PdfPageSize.A4;
// set PDF page orientation
htmlToPdfConverter.PdfDocumentOptions.PdfPageOrientation = PdfPageOrientation.Portrait;
// convert the HTML page from given URL to PDF in a buffer
byte[] pdfBytes = htmlToPdfConverter.ConvertUrl (urlToConvert.Text);
string documentsFolder = Environment.GetFolderPath (Environment.SpecialFolder.MyDocuments);
string outPdfFile = System.IO.Path.Combine (documentsFolder, "EvoHtmlToPdf.pdf");
// write the PDF buffer in output file
System.IO.File.WriteAllBytes (outPdfFile, pdfBytes);
// open the PDF document in the default PDF viewer
UIDocumentInteractionController pdfViewer = UIDocumentInteractionController.FromUrl (Foundation.NSUrl.FromFilename (outPdfFile));
pdfViewer.PresentOpenInMenu (this.View.Frame, this.View, true);
} catch (Exception ex) {
UIAlertView alert = new UIAlertView ();
alert.Title = "Error";
alert.AddButton ("OK");
alert.Message = ex.Message;
alert.Show ();
}
}
another
you can see thisurl

Related

Download the file as a zip in ASP.NET Core

I am designing an educational site. When the user downloads a training course, I want this download (training course) to be done in the form of compression (zipper), please give a solution
My code:
public Tuple<byte[],string,string> DownloadFile(long episodeId)
{
var episode=_context.CourseEpisodes.Find(episodeId);
string filepath = Path.Combine(Directory.GetCurrentDirectory(),
"wwwroot/courseFiles",
episode.FileName);
string fileName = episode.FileName;
if(episode.IsFree)
{
byte[] file = System.IO.File.ReadAllBytes(filepath);
return Tuple.Create(file, "application/force-download",fileName);
}
if(_httpContextAccessor.HttpContext.User.Identity.IsAuthenticated)
{
if(IsuserIncorse(_httpContextAccessor.HttpContext.User.Identity.Name,
episode.CourseId))
{
byte[] file = System.IO.File.ReadAllBytes(filepath);
return Tuple.Create(file, "application/force-download", fileName);
}
}
return null;
}
I write a demo to show how to download zip file from .net core:
First , Add NuGet package SharpZipLib , create an Image Folder in wwwroot and put some picture in it.
controller
public class HomeController : Controller
{
private IHostingEnvironment _IHosting;
public HomeController(IHostingEnvironment IHosting)
{
_IHosting = IHosting;
}
public IActionResult Index()
{
return View();
}
public FileResult DownLoadZip()
{
var webRoot = _IHosting.WebRootPath;
var fileName = "MyZip.zip";
var tempOutput = webRoot + "/Images/" + fileName;
using (ZipOutputStream IzipOutputStream = new ZipOutputStream(System.IO.File.Create(tempOutput)))
{
IzipOutputStream.SetLevel(9);
byte[] buffer = new byte[4096];
var imageList = new List<string>();
imageList.Add(webRoot + "/Images/1202.png");
imageList.Add(webRoot + "/Images/1data.png");
imageList.Add(webRoot + "/Images/aaa.png");
for (int i = 0; i < imageList.Count; i++)
{
ZipEntry entry = new ZipEntry(Path.GetFileName(imageList[i]));
entry.DateTime= DateTime.Now;
entry.IsUnicodeText = true;
IzipOutputStream.PutNextEntry(entry);
using (FileStream oFileStream = System.IO.File.OpenRead(imageList[i]))
{
int sourceBytes;
do
{
sourceBytes = oFileStream.Read(buffer, 0, buffer.Length);
IzipOutputStream.Write(buffer, 0, sourceBytes);
}while (sourceBytes > 0);
}
}
IzipOutputStream.Finish();
IzipOutputStream.Flush();
IzipOutputStream.Close();
}
byte[] finalResult = System.IO.File.ReadAllBytes(tempOutput);
if (System.IO.File.Exists(tempOutput)) {
System.IO.File.Delete(tempOutput);
}
if (finalResult == null || !finalResult.Any()) {
throw new Exception(String.Format("Nothing found"));
}
return File(finalResult, "application/zip", fileName);
}
}
when I click the downloadZip ,it will download a .zip file
The simple example that follows illustrates the use of the static ZipFile.CreateFromDirectory method which, despite the fact that it is in the System.IO.Compression namespace , actually resides in the System.IO.Compression.FileSystem assembly, so you need to add a reference to that in your controller.
[HttpPost]
public FileResult Download()
{
List<string> files = new List<string> { "filepath1", "filepath2" };
var archive = Server.MapPath("~/archive.zip");
var temp = Server.MapPath("~/temp");
// clear any existing archive
if (System.IO.File.Exists(archive))
{
System.IO.File.Delete(archive);
}
// empty the temp folder
Directory.EnumerateFiles(temp).ToList().ForEach(f => System.IO.File.Delete(f));
// copy the selected files to the temp folder
files.ForEach(f => System.IO.File.Copy(f, Path.Combine(temp, Path.GetFileName(f))));
// create a new archive
ZipFile.CreateFromDirectory(temp, archive);
return File(archive, "application/zip", "archive.zip");
}
Answer from Source - MikesDotNetting

Reading JSON File inside the Javascript adapter

MFP 8, Javascript adapters should read the JSON file (TestData.json) placed in
"\src\main\adapter-resources"
I need to read the static array contents from json/text file within the same JAVASCRIPT HTTP adapter. How to do the same ?
Read the static arrays from file (Text/JSON) within same adapter folder.
As explained in this solution, you can read a JSON file with Javascript as shown below.
function readFile(filename) {
var content = "";
var fileReader = new java.io.FileReader(filename);
var bufferedReader = new java.io.BufferedReader(fileReader);
var line;
while((line = bufferedReader.readLine()) != null) {
content += line;
}
bufferedReader.close();
return content;
}
function test() {
var file = 'yourfilename.json';
var fileContents;
try {
fileContents = JSON.parse(readFile(file));
} catch(ex) {
// handle error
}
return {
fileContents: fileContents
};

Downloaded file from folder includes %2F char on .NET Core

This must be a dumb question.
I have a web API Rest on c# that have an endpoint to generate and download an excel file. I use NPOI library.
It works fine if the file is generated within the root of my site. But when I try to move my file to a folder, file name include folder and de %2F char. I suppose this is an URL encode problem, but don't know how to fix it. This is my code.
[AllowAnonymous]
[HttpGet("ExportExcel")]
public async Task<IActionResult> ExportExcel(int activos = 1, int idarticulo = -1, string filtro = "", string ordenar = "", int ordenarsentido = 1)
{
var memory = new MemoryStream();
var newFile = #"Export/Articulos.xlsx";
//IArticulosService articulosService = new ArticulosService(_validation.sConnectionString, _validation.sEmpresa);
var mycon = _validation.GetConnectionStringFromClientID("ClientId1");
IArticulosService articulosService = new ArticulosService(mycon, "Ciatema");
try
{
// Genero el excel con el listado
articulosService.ExportarExcel(newFile, activos, filtro, ordenar, ordenarsentido);
using (var stream = new FileStream(newFile, FileMode.Open))
{
await stream.CopyToAsync(memory);
}
memory.Position = 0;
return File(memory, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", newFile);
}
catch (QueryFormatException ex)
{
return BadRequest(ex.Message);
}
catch (Exception ex)
{
System.Diagnostics.Debug.WriteLine(ex);
return StatusCode(StatusCodes.Status500InternalServerError);
}
}
Donwload filename is: Export%2FArticulos.xlsx when i need it to be only Articulos.xlsx.
Thanks!
you should be passing file name only instead of complete path in your return File method like below
return File(memory, "application/vnd.openxmlformats-officedocument.spreadsheetml.sheet", Path.GetFileName(newFile));

ASP.NET WebApi file upload using guid and file extension

I currently am able to save a file being uploaded to a WebAPI controller, but I'd like to be able to save the file as a guid with the correct file name extension so it can be viewed correctly.
Code:
[ValidationFilter]
public HttpResponseMessage UploadFile([FromUri]string AdditionalInformation)
{
var task = this.Request.Content.ReadAsStreamAsync();
task.Wait();
using (var requestStream = task.Result)
{
try
{
// how can I get the file extension of the content and append this to the file path below?
using (var fileStream = File.Create(HttpContext.Current.Server.MapPath("~/" + Guid.NewGuid().ToString())))
{
requestStream.CopyTo(fileStream);
}
}
catch (IOException)
{
throw new HttpResponseException(HttpStatusCode.InternalServerError);
}
}
HttpResponseMessage response = new HttpResponseMessage();
response.StatusCode = HttpStatusCode.Created;
return response;
}
I can't seem to get a handle on the actual filename of the content. I thought headers.ContentDisposition.FileName might be a candidate but that doesn't seem to get populated.
Thanks for the comments above which pointed me in the right direction.
To clarify the final solution, I used a MultipartFormDataStreamProvider which streams the file automatically. The code is in another question I posted to a different problem here:
MultipartFormDataStreamProvider and preserving current HttpContext
My full provider code is listed below. The key to generating the guid file name is to override the GetLocalFileName function and use the headers.ContentDisposition property. The provider handles the streaming of the content to file.
public class MyFormDataStreamProvider : MultipartFormDataStreamProvider
{
public MyFormDataStreamProvider (string path)
: base(path)
{ }
public override Stream GetStream(HttpContent parent, HttpContentHeaders headers)
{
// restrict what images can be selected
var extensions = new[] { "png", "gif", "jpg" };
var filename = headers.ContentDisposition.FileName.Replace("\"", string.Empty);
if (filename.IndexOf('.') < 0)
return Stream.Null;
var extension = filename.Split('.').Last();
return extensions.Any(i => i.Equals(extension, StringComparison.InvariantCultureIgnoreCase))
? base.GetStream(parent, headers)
: Stream.Null;
}
public override string GetLocalFileName(System.Net.Http.Headers.HttpContentHeaders headers)
{
// override the filename which is stored by the provider (by default is bodypart_x)
string oldfileName = headers.ContentDisposition.FileName.Replace("\"", string.Empty);
string newFileName = Guid.NewGuid().ToString() + Path.GetExtension(oldfileName);
return newFileName;
}
}

Error while uploading file method in Client Object Model Sharepoint 2010

Error while uploading file method in Client Object Model + Sharepoint 2010. Once the file got uploaded. After that though the code compiles with no error
I get the error while executing
"{"Value does not fall within the expected range."}
{System.Collections.Generic.SynchronizedReadOnlyCollection}
I have a method which takes care of functionality to upload files
///////////////////////////////////////////////////////////////////////////////////////////
public void Upload_Click(string documentPath, byte[] documentStream)
{
String sharePointSite = "http://cvgwinbasd003:28838/sites/test04";
String documentLibraryUrl = sharePointSite +"/"+ documentPath.Replace('\\','/');
////////////////////////////////////////////////////////////////////
//Get Document List
List documentsList = clientContext.Web.Lists.GetByTitle("Doc1");
var fileCreationInformation = new FileCreationInformation();
//Assign to content byte[] i.e. documentStream
fileCreationInformation.Content = documentStream;
//Allow owerwrite of document
fileCreationInformation.Overwrite = true;
//Upload URL
fileCreationInformation.Url = documentLibraryUrl;
Microsoft.SharePoint.Client.File uploadFile = documentsList.RootFolder.Files.Add(
fileCreationInformation);
//uploadFile.ListItemAllFields.Update();
clientContext.ExecuteQuery();
}
/////////////////////////////////////////////////////////////////////////////////////////////////
In the MVC 3.0 application in the controller I have defined the following method to invoke the upload method.
//////////////////////////////////////////////////////////////////////////////////////////////////
public ActionResult ProcessSubmit(IEnumerable<HttpPostedFileBase> attachments)
{
System.IO.Stream uploadFileStream=null;
byte[] uploadFileBytes;
int fileLength=0;
foreach (HttpPostedFileBase fileUpload in attachments)
{
uploadFileStream = fileUpload.InputStream;
fileLength=fileUpload.ContentLength;
}
uploadFileBytes= new byte[fileLength];
uploadFileStream.Read(uploadFileBytes, 0, fileLength);
using (DocManagementService.DocMgmtClient doc = new DocMgmtClient())
{
doc.Upload_Click("Doc1/Doc2/Doc2.1/", uploadFileBytes);
}
return RedirectToAction("SyncUploadResult");
}
//////////////////////////////////////////////////////////////////////////////////////////////////
Please help me to locate the error
I think your documentLibraryUrl needs to be relative. This is working for me with Sharepoint 2013
[HttpPost]
[ValidateAntiForgeryToken]
[SharePointContextFilter]
public ActionResult Upload()
{
if (Request.Files.Count > 0)
{
HttpPostedFileBase file = Request.Files[0];
if (file != null && file.ContentLength > 0)
{
var fileName = Path.GetFileName(file.FileName);
var spContext = SharePointContextProvider.Current.GetSharePointContext(HttpContext);
using (var clientContext = spContext.CreateUserClientContextForSPHost())
{
if (clientContext != null)
{
FileCreationInformation newFile = new FileCreationInformation();
using (MemoryStream ms = new MemoryStream())
{
file.InputStream.CopyTo(ms);
byte[] array = ms.GetBuffer();
newFile.Content = array;
}
List docs = clientContext.Web.Lists.GetByTitle("Documents");
Folder folder = docs.RootFolder;
clientContext.Load(folder);
clientContext.ExecuteQuery();
newFile.Url = docs.RootFolder.ServerRelativeUrl + "/" + fileName;
Microsoft.SharePoint.Client.File uploadFile = docs.RootFolder.Files.Add(newFile);
clientContext.Load(uploadFile);
clientContext.ExecuteQuery();
//Set the metadata
Microsoft.SharePoint.Client.ListItem item = uploadFile.ListItemAllFields;
string docTitle = string.Empty;
item["Title"] = docTitle;
item.Update();
clientContext.ExecuteQuery();
}
}
}
}
return RedirectToAction("Index", new { SPHostUrl = SharePointContext.GetSPHostUrl(HttpContext.Request).AbsoluteUri });
}