I know its a known topic in many forums and blogs. I read many articles. And many of them are quiet informative. But for me it seems like it demands new approach to achieve this task.
Am looking for a solution to print a html on server side. But after working with many options i realised that we
cant give printer name or
its printing html raw content like a txt file
Later came to know about ghostscript (https://stackoverflow.com/a/2600189/1238159) can be used to print a PDF on server side silently.
Also tried with crystal report (but how to pass HTML content to it dynamically eventhough it wont support many tags), itextsharp, ssrs, pdfsharp etc etc but none of them were supporting many of the HTMl tags & W3C standards. So i ended at one point to generate PDF. Only wkhtmltopdf is perfect for converting html to pdf. it supports every html tag unlike anyother as of my experience. but printing PDf is the question for me from many years.
But now am facing a problem even with GhostScript (am using ver 9.05). With localhost i can use it perfectly. i can print on server side to what ever printer name coming from UI silently. but with the IP address or machine name its not working. i even implemented Impersonation. Even though the process gets hanged while calling GhostScript.
Now what i want to get clear is
Is it possible to print a html or pdf (actual content) on server side?
Any open source tools are there to achieve this
printer name I would like to pass dynamically
Any clue or workaround might help many hours of people around the globe. :)
Many thanks in advance.
Regards,
Pavan N
After using the suggestion by Lau. am able to do it in command prompt (means cmd.exe runs under my account). but my application will run under network service.
Now am getting a problem just a kind of this ACCESS Denied
Yeah. Finally i was able to start the process. and am able to see my gswin32c.exe process under task manager with my domain credentials. code is as follows:
public bool PrintVSPDF(string ghostScriptPath, int numberOfCopies, string printerName, string pdfFileName)
{
Logger.AddToLog("printerName", printerName);
string impersonationUsername = "";
string impersonationDomain = "";
string impersonationPWD = "";
if (ConfigurationManager.AppSettings["UName"] != null)
{
impersonationUsername = Encryption.Decrypt(ConfigurationManager.AppSettings["UName"].ToString(), Encryption.DEFAULT_KEY, Encryption.DEFAULT_SEED);
impersonationDomain = impersonationUsername.Split('\\').Count() > 1 ? impersonationUsername.Split('\\')[0] : "";
impersonationUsername = impersonationUsername.Split('\\').Count() > 1 ? impersonationUsername.Split('\\')[1] : impersonationUsername.Split('\\')[0];
}
if (ConfigurationManager.AppSettings["PD"] != null)
{
impersonationPWD = Encryption.Decrypt(ConfigurationManager.AppSettings["PD"].ToString(), Encryption.DEFAULT_KEY, Encryption.DEFAULT_SEED);
}
using (Impersonation imp = new Impersonation(impersonationUsername, impersonationDomain, impersonationPWD))
{
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.Arguments = "-dPrinted -dNoCancel -dNOPAUSE -dBATCH -dNumCopies=" + Convert.ToString(numberOfCopies) + " -sDEVICE=mswinpr2 -sOutputFile=%printer%\"" + printerName + "\" \"" + pdfFileName + "\" ";
startInfo.FileName = ghostScriptPath;
startInfo.UseShellExecute = false;
startInfo.CreateNoWindow = true;
//startInfo.RedirectStandardInput = true;
startInfo.RedirectStandardError = true;
startInfo.RedirectStandardOutput = true;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
startInfo.UserName = impersonationUsername;
startInfo.Domain = impersonationDomain;
SecureString ss = new SecureString();
for (int i = 0; i < impersonationPWD.Length; i++)
{
ss.AppendChar(impersonationPWD[i]);
}
startInfo.Password = ss;
Process process = null;
try
{
process = Process.Start(startInfo);
//Logger.AddToLog("Error VS", process.StandardError.ReadToEnd());
//Logger.AddToLog("Output VS", process.StandardOutput.ReadToEnd());
//Logger.AddToLog(process.StartInfo.Arguments.ToString(), "VS Print Arguments");
//Console.WriteLine(process.StandardError.ReadToEnd() + process.StandardOutput.ReadToEnd());
//Logger.AddToLog(process.StartInfo.FileName.ToString(), "VS Print file name");
process.WaitForExit(30000);
if (process.HasExited == false)
process.Kill();
int exitcode = process.ExitCode;
process.Close();
return exitcode == 0;
}
catch (Exception ex)
{
Logger.AddToLog(ex);
return false;
}
}
}
But the process is working perfectly in localhost:5030 ie., while running from my visual studio. but with IP address or machine name. it just hangs and throws this error
Same thing is happening for adobe reader, foxit, etc etc.
( Process must exit before requested information can be determined. : at System.Diagnostics.Process.EnsureState(State state)
at System.Diagnostics.Process.get_ExitCode() )
I have been working on a project that is doing just this. It has been a very frustrating experience. The most reliable method I have found is to export my reports to PDF and then use Foxit Reader (NOT Adobe Reader due to security problems) via Diagnostics.Process to print the document.
The printer name can be supplied to the Foxit Reader command line args.
The environment I am working with is ASP.net 3.5 on IIS 7 on Windows Server 2008 R2 x64.
I am also using Sql Server Reporting Services.
Maybe this code will help you out:
public FileContentResult GetPOReport(DataTable reportData, int poNumber, string copies, out string fileName, out string downloadPath)
{
fileName = "PO_" + poNumber.ToString().Trim() + "_" + DateTime.Now.ToString("yyyy-MM-dd_HH-mm-ss") + ".pdf";
downloadPath = "/Generated/" + fileName;
var outputFiles = new Dictionary<string, string>
{
{"", Server.MapPath("~" + downloadPath)}
};
if (!string.IsNullOrWhiteSpace(copies))
{
var copyList = copies.Split(new[] { ',' }, StringSplitOptions.RemoveEmptyEntries);
foreach (var temp in copyList)
outputFiles.Add(temp, Server.MapPath("~" + "/Generated/" + temp.Trim() + ".pdf"));
}
FileContentResult returnFile = null;
foreach (var outputFile in outputFiles)
{
var file = WriteReportToDisk(reportData, outputFile.Value, outputFile.Key);
if (file == null)
continue;
if (string.IsNullOrWhiteSpace(outputFile.Key))
returnFile = file;
else
PrintReport(outputFile.Value);
}
return returnFile;
}
public void PrintReport(string filePath)
{
try
{
if (!ConfigurationManager.AppSettings.AllKeys.Contains("AdobeReaderPath") ||
!ConfigurationManager.AppSettings.AllKeys.Contains("AdobePrintParameters") ||
!ConfigurationManager.AppSettings.AllKeys.Contains("PrinterName"))
return;
var adobeReaderPath = ConfigurationManager.AppSettings["AdobeReaderPath"].Trim();
var adobePrintParameters = ConfigurationManager.AppSettings["AdobePrintParameters"].Trim();
var printerName = ConfigurationManager.AppSettings["PrinterName"].Trim();
var printProcessDomain = ConfigurationManager.AppSettings["PrintProcessDomain"].Trim();
var printProcessUserName = ConfigurationManager.AppSettings["PrintProcessUserName"].Trim();
var printProcessPassword = ConfigurationManager.AppSettings["PrintProcessPassword"].Trim();
var userPrinter = Entities.UserPrinters.FirstOrDefault(p => p.UserName == User.Identity.Name);
if (userPrinter != null)
printerName = userPrinter.PrinterName.Trim();
using (var process = new Process
{
StartInfo =
new ProcessStartInfo(
adobeReaderPath,
string.Format(adobePrintParameters, filePath, printerName)
)
})
{
if (!string.IsNullOrWhiteSpace(printProcessUserName))
{
if (!string.IsNullOrWhiteSpace(printProcessDomain))
process.StartInfo.Domain = printProcessDomain;
process.StartInfo.UserName = printProcessUserName;
var securePassword = new SecureString();
foreach (var passwordCharacter in printProcessPassword)
securePassword.AppendChar(passwordCharacter);
process.StartInfo.Password = securePassword;
process.StartInfo.UseShellExecute = false;
process.StartInfo.CreateNoWindow = true;
process.StartInfo.LoadUserProfile = true;
}
process.Start();
process.WaitForExit(30000);
}
}
catch (Exception exception)
{
EventLog.WriteEntry("PO Suggestion Viewer", string.Format("PO Suggestion Viewer Error:\n{0}", exception.Message));
throw;
}
}
public FileContentResult WriteReportToDisk(DataTable reportData, string filePath, string copy)
{
var webReport = new WebReport()
{
ExportFileName = "PO Report",
ReportPath = Server.MapPath("~/Reports/PurchaseOrderReport.rdlc")
};
if (!string.IsNullOrWhiteSpace(copy))
webReport.ReportParameters.Add(new ReportParameter("Copy", copy));
if ((User != null) && (User.Identity != null) && (User.Identity.Name != null))
webReport.ReportParameters.Add(new ReportParameter("User", User.Identity.Name));
webReport.ReportDataSources.Add(new ReportDataSource("ReportData", reportData));
var report = webReport.GetReport();
Response.AddHeader("content-disposition", string.Format("attachment; filename={0}.{1}", webReport.ExportFileName, webReport.FileNameExtension));
Response.ContentType = "application/pdf";
var file = File(report, webReport.MimeType, "POReport");
System.IO.File.WriteAllBytes(filePath, file.FileContents);
return file;
}
My web.config contains:
<appSettings>
<add key="webpages:Version" value="1.0.0.0" />
<add key="ClientValidationEnabled" value="true" />
<add key="UnobtrusiveJavaScriptEnabled" value="true" />
<add key="AdobeReaderPath" value="C:\Program Files (x86)\Foxit Software\Foxit Reader\Foxit Re-ader.exe" />
<add key="AdobePrintParameters" value="-t "{0}" "{1}"" />
<add key="PrinterName" value="HP_Office" />
<add key="PrintProcessDomain" value="DOMAIN_NAME" />
<add key="PrintProcessUserName" value="DOMAIN_USER" />
<add key="PrintProcessPassword" value="DOMAIN_PASSWORD" />
</appSettings>
sorry for the late posting. i taught i already answered this Q.
I found a work around to convert html to pdf.
am using WKHTMLTOPDF API to convert the html to pdf. and it looks awesome compared to many commercial products out there. am able to get coloured/greyscale, margins, indexing. and many more.
here is the link i followed
http://code.google.com/p/wkhtmltopdf/
ProcessStartInfo startInfo = new ProcessStartInfo();
startInfo.FileName = AppDomain.CurrentDomain.BaseDirectory + #"\bin\wkhtmltopdf.exe";
pdfFile = localReportPath + "\\Reports\\Savedfiles\\" + filename + ".pdf";
//Ref: http://madalgo.au.dk/~jakobt/wkhtmltoxdoc/wkhtmltopdf-0.9.9-doc.html
startInfo.Arguments = " --minimum-font-size 16 --margin-left 10mm --margin-right 10mm --zoom 3 " + htmlFile + " " + pdfFile;
startInfo.WindowStyle = ProcessWindowStyle.Hidden;
Process p = Process.Start(startInfo);
p.WaitForExit();
p.Dispose();
p.Close();
and the same i sent for ghostscript to get an beautiful TIFF file for faxing. performance is good with huge data also.
Regards,
Pavan N
Related
Back few days i'm trying to make a web application that convert url to pdf. Finally i have done this with the help of wkhtmltopdf.exe
My class code is given below
public class PDFGenerator
{
public static string HtmlToPdf(string pdfOutputLocation, string outputFilenamePrefix, string[] urls,
string[] options = null,
string pdfHtmlToPdfExePath = "C:\\Program Files\\wkhtmltopdf\\bin\\wkhtmltopdf.exe")
{
string urlsSeparatedBySpaces = string.Empty;
try
{
//Determine inputs
if ((urls == null) || (urls.Length == 0))
throw new Exception("No input URLs provided for HtmlToPdf");
else
urlsSeparatedBySpaces = String.Join(" ", urls); //Concatenate URLs
string outputFolder = pdfOutputLocation;
string outputFilename = outputFilenamePrefix + "_" + DateTime.Now.ToString("yyyy-MM-dd-hh-mm-ss-fff") + ".PDF"; // assemble destination PDF file name
var p = new System.Diagnostics.Process()
{
StartInfo =
{
FileName = pdfHtmlToPdfExePath,
Arguments = ((options == null) ? "" : String.Join(" ", options)) + " " + urlsSeparatedBySpaces + " " + outputFilename,
UseShellExecute = false, // needs to be false in order to redirect output
RedirectStandardOutput = true,
RedirectStandardError = true,
RedirectStandardInput = true, // redirect all 3, as it should be all 3 or none
WorkingDirectory = HttpContext.Current.Server.MapPath(outputFolder)
}
};
p.Start();
// read the output here...
var output = p.StandardOutput.ReadToEnd();
var errorOutput = p.StandardError.ReadToEnd();
// ...then wait n milliseconds for exit (as after exit, it can't read the output)
p.WaitForExit(60000);
// read the exit code, close process
int returnCode = p.ExitCode;
p.Close();
// if 0 or 2, it worked so return path of pdf
if ((returnCode == 0) || (returnCode == 2))
return outputFolder + outputFilename;
else
throw new Exception(errorOutput);
}
catch (Exception exc)
{
throw new Exception("Problem generating PDF from HTML, URLs: " + urlsSeparatedBySpaces + ", outputFilename: " + outputFilenamePrefix, exc);
}
}
}
and my button click event code is given below
//Create PDF from a single URL
var pdfUrl = PdfGenerator.PDFGenerator.HtmlToPdf(pdfOutputLocation: "~/PDFs/",
outputFilenamePrefix: "GeneratedPDF",
urls: new string[] { "http://news.bbc.co.uk" });
//Create PDF from multiple URLs
pdfUrl = PdfGenerator.PDFGenerator.HtmlToPdf(pdfOutputLocation: "~/PDFs/",
outputFilenamePrefix: "GeneratedPDF",
urls: new string[] { "http://www.google.co.uk", "http://news.bbc.co.uk" });
all code is working properly and saving pdf in my PDFs code. But i have 2 questions:
This code is not working when i host my website because C:\\Program Files\\wkhtmltopdf\\bin\\wkhtmltopdf.exe executing error. Is any dll library avail for wkhtmltopdf?
When i run this code pdf saved in silent mode. I want to know that is this possible to save pdf with save dialog or ask user to folder location where they want to save pdf?
Sorry for my bad english.
Place your "wkhtmltopdf.exe" in your project folder, so that it can be easily accessible to your application. There might be some access related issues if you have your .exe file in 'C' folder. Try this, it worked for me.
I was trying to automate server patch installation for my product and I came to know about Wix Toolset.
I was hoping to get the JBoss Version in my installer. The command to get the same is standalone.bat --version from cmd.
So from my installer I created one CustomAction where I tried to run it and get the output.
public static string runRunnableBatch(string path){
Process exploitVersionService = new Process();
string runnableBinPath = path;
exploitVersionService.StartInfo.WorkingDirectory = path + "bin";
exploitVersionService.StartInfo.FileName = path + "bin\\standalone.bat";
exploitVersionService.StartInfo.CreateNoWindow = false;
exploitVersionService.StartInfo.Arguments = string.Format("--version");
exploitVersionService.StartInfo.UseShellExecute = false;
exploitVersionService.StartInfo.RedirectStandardOutput = true;
exploitVersionService.StartInfo.RedirectStandardInput = false;
exploitVersionService.Start();
exploitVersionService.WaitForExit();
// /*
string opt = "";
while (!exploitVersionService.StandardOutput.EndOfStream){
opt += exploitVersionService.StandardOutput.ReadLine();
}
// */
//using (StreamWriter writer = new StreamWriter("D:\\_log.txt"))
//using (StreamReader reader = exploitVersionService.StandardOutput){
// writer.AutoFlush = true;
// for (; ; ){
// string textLine = reader.ReadLine();
// if (textLine == null)
// break;
// writer.WriteLine(textLine);
// }
//}
//StreamReader exploitVersionFeed = exploitVersionService.StandardOutput;
//string output = exploitVersionFeed.ReadToEnd();
return opt;
}
When I was doing that, all I got as output was the first line of the whole output string.
I needed the whole string in my code so that from regular expression I could extract the version.
Also tried with
public static string runRunnableBatch(string path){
string executableBinPath = path + "bin";
string executableBinPath_BatchCmd = "cd " + "\"" + executableBinPath + "\"";
string outputFileName = "TempVerInfoHolder.txt";
string outputFilePath = executableBinPath+#"\TempVerInfoHolder1.txt";
string versionRetriever_BatchCmd = #"standalone.bat --version > " + "\""+outputFilePath+"\"";
string partitionName_BatchCmd = #Strings.Utils.getPartitionFromPath(path);
// Creating command sequence
SortedList<int, string> commandSequence = new SortedList<int, string>();
// ~ d:
commandSequence.Add(1, partitionName_BatchCmd);
// ~ cd %path%
commandSequence.Add(2, executableBinPath_BatchCmd);
// ~ standalone.bat --version > %filename%
commandSequence.Add(3, versionRetriever_BatchCmd);
runCommandFromSequence(commandSequence);
// Run together
return "";
}
private static void runCommandFromSequence(SortedList<int, string> commandSequence){
Process seqCmdExecHost = new Process();
ProcessStartInfo psi = new ProcessStartInfo();
psi.FileName = "cmd.exe";
psi.RedirectStandardInput = true;
psi.RedirectStandardOutput = true;
psi.UseShellExecute = false;
psi.CreateNoWindow = false;
seqCmdExecHost.StartInfo = psi;
seqCmdExecHost.Start();
using (StreamWriter writer = seqCmdExecHost.StandardInput) {
if (writer.BaseStream.CanWrite) {
foreach (int item in commandSequence.Keys){
MessageBox.Show(seqCmdExecHost.Id.ToString());
MessageBox.Show(commandSequence[item]);
writer.WriteLine(commandSequence[item]);
}
}
string opt = "";
while (!seqCmdExecHost.StandardOutput.EndOfStream){
opt += seqCmdExecHost.StandardOutput.ReadLine();
}
MessageBox.Show("Exited? " + seqCmdExecHost.HasExited);
MessageBox.Show("O/P? " + opt);
}
}
I have tried some other way as well. Switching the commented code of the above function was one of them.
Output getting while doing it from code level
Calling "D:\Servers\VA\XYZ\JBoss-7.1.1-Final\bin\standalone.conf.bat
Output while running the same command manually from cmd
Calling D:\Servers\VA\XYZ\JBoss-7.1.1-Final\bin\standalone.conf.bat
======================================================================
JBoss Bootstrap Environment
JBOSS_HOME: D:\Servers\VA\XYZ\JBoss-7.1.1-Final
JAVA: C:\Program Files\Java\jdk1.7.0_67\bin\java
JAVA_OPTS
======================================================================
Listening for transport dt_socket at address: 8787
19:08:08,333 INFO [org.jboss.modules] JBoss Modules version 1.1.1.GA
JBoss AS 7.1.1.Final "Brontes"
Press any key to continue . . .
My observation is, the stream is getting closed once the nested standalone.conf.bat is getting called from standalone.bat.
If any workaround available to get the full output in string/buffer/stream, would be appreciated.
Thanks
What you could do is call the Command line Application instead of calling the batch file
exploitVersionService.StartInfo.WorkingDirectory = path + "bin";
exploitVersionService.StartInfo.FileName = "cmd.exe";
exploitVersionService.StartInfo.CreateNoWindow = false;
exploitVersionService.StartInfo.Arguments = string.Format(" /c \"{0}\" --version",path + "bin\\standalone.bat");
I found one work around to do achieve this.
I created the batch file programmatically and ran it with cmd.
public static void createBatchToGetVersion(string path)
{
CustomLogger.getInstance().debug("Started creating batch file");
BatchOps.executableBinPath = path + "bin";
CustomLogger.getInstance().debug("Ëxecutable bin path: " + BatchOps.executableBinPath);
BatchOps.tempBatchFileName = "JBossVerCmd.bat";
BatchOps.holderFileName = #"JBossVerHolder.txt";
BatchOps.absoluteHolderPath = Strings.Utils.normalize(executableBinPath) + holderFileName;
CustomLogger.getInstance().debug("Normalized absoluteHolderPath: " + BatchOps.absoluteHolderPath);
CustomLogger.getInstance().debug("Checking if JBOSS_HOME entered by user actuallty points to JBOSS");
if (!File.Exists(Strings.Utils.normalize(executableBinPath) + "standalone.bat"))
{
CustomLogger.getInstance().error("standalone.bat not found. JBOSS_HOME Dir is not correctly entered");
throw new CustomExceptions.DirectoryNotAcceptableException("Bad directory is assigned to JBOSS_HOME or JBOSS_HOME structure corrupted");
}
/*
* Batch file formation.
* Contains:
* Start file
* D:
* cd D:\Fusion Server\jboss 7.1.1\bin
* #echo | call standalone.bat --version > sample.txt
* #echo Done
* End file
* #echo is required here because it exits the cmd when completed whithout having the user pressing any key
*/
string changePartition_cmd = Strings.Utils.getPartitionFromPath(path);
string changeDirectory_cmd = #"cd " + BatchOps.executableBinPath;
string getVersion_cmd = #"#echo | call standalone.bat --version > " + holderFileName;
string exitCmd = #"#echo Done";
CustomLogger.getInstance().debug("Command to be written on batch file");
CustomLogger.getInstance().debug("\r\n" + changePartition_cmd + "\r\n" + changeDirectory_cmd + "\r\n" + getVersion_cmd + "\r\n" + exitCmd);
SortedList<int, string> commandSequence = new SortedList<int, string>();
CustomLogger.getInstance().debug("Initializing command sequence.");
commandSequence.Add(1, changePartition_cmd);
commandSequence.Add(2, changeDirectory_cmd);
commandSequence.Add(3, getVersion_cmd);
commandSequence.Add(4, exitCmd);
// Will create one if file never existed and open one delete the content and set the pointer to the begnning
// if already existed
StreamWriter batchFileWriter = null;
try
{
CustomLogger.getInstance().debug("Establishing stream to and from temp batch file");
batchFileWriter = new StreamWriter(tempBatchFileName);
CustomLogger.getInstance().debug("Command sequence ready to be written on temp batch file.");
Perform.writeToStreamFromSequence(batchFileWriter, commandSequence);
CustomLogger.getInstance().debug("Command sequence successfully written");
}
catch (IOException ex)
{
CustomLogger.getInstance().error("Error while writing command sequence.\n" + ex.ToString());
// throw exception to CustomAction
throw new IOException("Error while writing commandSequence");
}
finally
{
// Not required. Stream already closed in writeToStreamFromSequence
}
}
public static void runTempBatchFile()
{
Process seqCmdExecHost = new Process();
ProcessStartInfo procStartInfo = new ProcessStartInfo("cmd", #"/c " + BatchOps.tempBatchFileName);
procStartInfo.WindowStyle = ProcessWindowStyle.Hidden;
seqCmdExecHost.StartInfo = procStartInfo;
seqCmdExecHost.Start();
seqCmdExecHost.WaitForExit();
seqCmdExecHost.Close();
}
I found the moment i was doing
procStartInfo.UseShellExecute=true;
procStartInfo.RedirectStandardOutput=true
It was giving the first line of output. Dont know why?. If anyone has any idea about it please explain.
Thanks
You guys Have seen Youtube right. There while you are watching a video, You will also get related videos preview alongwith link. So how we can get it from video itself.. Is it possible to do so.. I am able to get the url from database and display it.. and when the link is clicked it will be played in a jquery player.. So before that a preview of that or you can say playlist of that will be available for user.
I have updated my code with a link I found.. But still I am not able to get the Image from Video.. Is there anything wrong in my code.. Please correct me if I am wrong..
Below is my front end code:
<form id="form1" runat="server">
<div id="examples" runat="server" style="height:100%;width:100%">
<div id="vidhead">Latest Videos</div>
</div>
</form>
and I am adding all my video links from backend on page load as shown below:
try
{
con.Open();
com = new SqlCommand("Select videourl, videoname from video order by [vid] desc",con);
DbDataReader dr = com.ExecuteReader();
DataTable dt = new DataTable();
if (dr.HasRows)
{
int i = 0;
dt.Load(dr);
int rows = dt.Rows.Count;
for (i = 0; i < rows; i++)
{
HtmlGenericControl d = new HtmlGenericControl("div");
HtmlGenericControl s = new HtmlGenericControl("span");
string[] link = new string[rows];
string[] name = new string[rows];
d.Attributes.Add("class", "plst");
s.Attributes.Add("class", "text");
link[i] = dt.Rows[i]["videourl"].ToString();
name[i] = dt.Rows[i]["videoname"].ToString();
string videothumb = link[i];
string svthto="**Path to save Image**";
string imgpath=GetVideoThumbnail(videothumb, svthto, 30);
sb.Append("<a id=" + "\"a" + i + "\"" + " href=" + "\"" + link[i] + "\"" + " class=" + "\"links\"" + ">" + name[i] + "</a>");
s.InnerHtml = sb.ToString();
d.Controls.Add(s);
examples.Controls.Add(d);
sb.Clear();
}
}
}
catch(Exception ex)
{
ex.Message.ToString();
}
public string GetVideoThumbnail(string path, string saveThumbnailTo, int seconds)
{
string parameters = string.Format("-ss {0} -i {1} -f image2 -vframes 1 -y {2}", seconds, path, saveThumbnailTo);
string pathToConvertor = "C:\\Program Files\\ffmpeg\\ffmpeg.exe";
var processInfo = new ProcessStartInfo();
processInfo.FileName = pathToConvertor;
processInfo.Arguments = parameters;
processInfo.CreateNoWindow = true;
processInfo.UseShellExecute = false;
File.Delete(saveThumbnailTo);
using (var process = new Process())
{
process.StartInfo = processInfo;
process.Start();
process.WaitForExit();
}
if (File.Exists(saveThumbnailTo))
return saveThumbnailTo;
else
return "File not Found";
}
and here is the image of what I am getting until now:
Please note: I am not concentrating on you tube videos. I am questioning regarding the videos which I store in server side folder. So if there is any jquery technique or any sort of technique to do this then please let me know.:)
Yes, it's possible to do what you're trying to do. First, you'll need to parse out the ID of the video from the URL. For example, take this video (first YouTube video that came up when searching stackoveflow, FYI) URL: http://www.youtube.com/watch?v=zsYjsgm4Psg. The video ID of that is zsYjsgm4Psg. Quoting #Asaph from this post,
Each YouTube video has 4 generated images. They are predictably
formatted as follows:
http://img.youtube.com/vi/<insert-youtube-video-id-here>/0.jpg
http://img.youtube.com/vi/<insert-youtube-video-id-here>/1.jpg
http://img.youtube.com/vi/<insert-youtube-video-id-here>/2.jpg
http://img.youtube.com/vi/<insert-youtube-video-id-here>/3.jpg
#Asaph from the linked post provides more information about the different images that are available for a video. For now, suffice it to know that 1.jpg is one of the thumbnails for the video. Using the video ID from above, we can build up a URL for a thumbnail as such
You're going to need an image on the client side obviously, and you'll need to set that image element's source to the thumbnail URL you generate as shown above.
I dont know if you can pull this out using the magic of html5 and JavaScript these days but the way I traditionally know of achieving video manipulation on the server side is to use a popular command line video conversion utility call ffmpeg.
It can be downloaded at http://www.ffmpeg.org/.
With a quick search I found this forum post which contained the following snippet of code:
string videothumb = uniquefilename + fileExt;
Process p;
ProcessStartInfo info = new ProcessStartInfo();
info.FileName = "D:\\web\\upload\\ffmpeg.exe";
info.WindowStyle = ProcessWindowStyle.Hidden;
info.Arguments = " -i " + "D:\\web\\upload\\files\\" + videothumb + " -vframes 25 -f image2 -vcodec mjpeg " + "D:\\web\\upload\\thumbnails\\" + uniquefilename + "%d.jpg";
p = Process.Start(info);
while (!p.HasExited) { Thread.Sleep(10); }
Now that doesn't seem like the best piece of code I've ever seen but it should get you started.
Further down the linked thread they also solve how to control which thumbnails are generated.
First of all I would like to thank #rtpHarry who introduced me to ffmpeg.. otherwise I wouldn't come to know about how to achieve this.. This might not be the only way.. But this was good way for me.. :) Thanks #rtpHarry.. +50 for that... :)
Well after a long search I have come up with this solution and it looks cool and fine now and this is what I was expecting.. :)
This is what I do in backend page load event.
con.Open();
com = new SqlCommand("Select * from video order by [vid] desc", con);
string thumbname = "";
string newthumb = "";
string newpath = "";
reader = com.ExecuteReader();
if (reader.HasRows)
{
dt.Load(reader);
int rows = dt.Rows.Count;
int i = 0;
for (i = 0; i < rows; i++)
{
int[] id = new int[rows];
string[] link=new string[rows];
string[] nid = new string[rows];
id[i] = Convert.ToInt32(dt.Rows[i]["vid"].ToString());
link[i] = dt.Rows[i]["videourl"].ToString();
nid[i]=id[i].ToString();
thumbname = Server.MapPath("~//Images//Video_Thumbs//") + nid[i] + ".jpg";
newthumb = nid[i] + ".jpg";
string link1 = Server.MapPath("~//Videos//") + link[i];
string param = String.Format("-ss {0} -i \"" + link1 + "\" -s 150*120 -vframes 1 -f image2 -vcodec mjpeg \"" + thumbname + "\"",20);
Process p = new Process();
p.StartInfo.Arguments = param;
p.StartInfo.FileName = Server.MapPath("~\\ffmpeg\\ffmpeg.exe");
p.StartInfo.CreateNoWindow = true;
p.StartInfo.UseShellExecute = false;
p.Start();
newpath="Images//Video_Thumbs//"+newthumb.ToString();
com1 = new SqlCommand("update video set vidthumb='" + newpath + "' where vid=" + id[i] + "", con);
com1.ExecuteNonQuery();
}
}
con.Close();
As of now I have not designed the fileupload part for the videos so I have written this code in page load. So when ever the page loads the videos from the table "Video" will be retrieved one by one and a frame at 20sec time will be captured and saved in a specific folder and also in table "Video". Actually, the problem was, it was not recognizing the Server.Mappath without "~" sign before the path. Now its working well and fine and here is the image of what I was expecting... :)
If anyone visits checks this question and answer and if anyone has some doubt then please comment here.. It will be my pleasure to help you people... and Great thanks to ffmpeg.. :)
Presently I'm using the following lines of c# code to automatically print a pdf file to a mobile printer:
string defFile = (Path.Combine(System.Windows.Forms.Application.StartupPath, tkt_no + "_DEF.pdf"));
string rwPrinter = "";
if (GlobalVars.useDefaultPrinter == false)
{
foreach (string strPrinter in System.Drawing.Printing.PrinterSettings.InstalledPrinters)
{
if (strPrinter.StartsWith("ZDesigner"))
{
rwPrinter = strPrinter;
break;
}
}
}
if (jobdo.Equals("print"))
{
Process process = new Process();
process.StartInfo.FileName = defFile;
if (rwPrinter.Length > 0)
{
process.StartInfo.Verb = "printto";
process.StartInfo.Arguments = "\"" + rwPrinter + "\"";
}
else
{
process.StartInfo.Verb = "print";
}
process.Start();
process.WaitForInputIdle();
Thread.Sleep(10000);
process.Kill();
These above lines are good if the application is on a workstation desktop, but the problem I am having is when it actually prints the pdf file from a Citrix App shortcut, it spawns Adobe Reader (the default for pdf) and doesn't close when print job is done.
So my question is, is there any way to print a pdf document without opening Adobe or similar? Perhaps in the iTextSharp library which I'm using in the same application to populate fields?
One of the methods i used :
PrintDocument doc = new PrintDocument();
doc.PrinterSettings.PrinterName = "printername";
string[] files = Directory.GetFiles("D:\\Invoice");
foreach (string file in files)
{
string fname = Path.GetFileName(file);
doc.DocumentName = fname;
doc.Print();
Console.WriteLine(file);
}
This gives an exception on the doc.Print() line.
"Settings to access printer 'printername' are not valid."
The other method i used :
Process printJob = new Process();
printJob.StartInfo.FileName = #"C:\Program Files (x86)\Adobe\Reader 10.0\Reader\AcroRD32.exe";
printJob.StartInfo.UseShellExecute = false;
printJob.StartInfo.Verb = "Print";
printJob.StartInfo.CreateNoWindow = true;
printJob.StartInfo.WindowStyle = ProcessWindowStyle.Hidden;
printJob.StartInfo.Arguments = "\"" + printerAddress + "\"";
string[] files = Directory.GetFiles("D:\\Invoice");
foreach (string file in files)
{
string fname = Path.GetFileName(file);
printJob.StartInfo.WorkingDirectory = Path.GetDirectoryName(fname);
printJob.Start();
//Console.WriteLine(fname);
}
This gives an error after printJob.Start(). As it is pdf file, it opens the Adobe reader and displays the error message there. Hopw it explains.
"There was an error opening the document. The file could not be found."
Can anyone help me on these issues?
In 2nd snippet, this seems wrong:
string fname = Path.GetFileName(file);
printJob.StartInfo.WorkingDirectory = Path.GetDirectoryName(fname);
printJob.Start();
You just set WorkingDirectory. How does printJob get the actual file name?
In 1st snippet, you are probably not setting everything. Have you checked the MSDN documentation? It's generally a good idea to try to find, then read and try to understand the docs, before asking at SO...