Get image from url in database - c#

I have a database with image URL's. I have a stored procedure hat GET's the url's (SP_GET_Image) I want execute the stored proc then for each of the URL's get the image.
I want the actual image locally not the url.
Then for each image I want to save them locally. I have this code but want to know how do I save each image in a datarow.
I have started with the code.
Dim CMD as new sqlCommand("StoredProcedureName")
CMD.parameters("#Parameter1", sqlDBType.Int).value = Param_1_value
Dim connection As New SqlConnection(connectionString)
CMD.Connection = connection
CMD.CommandType = CommandType.StoredProcedure
Dim adapter As New SqlDataAdapter(CMD)
adapter.SelectCommand.CommandTimeout = 300
'Fill the dataset'
Dim DS as DataSet
adapter.Fill(ds)
connection.Close()
'Now, read through your data:'
For Each DR as DataRow in DS.Tables(0).rows
'<-- Im not sure here how to GET EACH images locally saved.
Next
c# or vb help is fine.
The url looks like this :
http://img.myCompany.net/p/1483/278227_20094171232290.jpg

You can use My.Computer.Network.DownloadFile in order to download and store the file on local machine or a remote server supplying a user name and password (if required). As you need to specify the file name when downloading, you can extract it from the URL with SubString(URL.LastIndexOf("/") + 1)
For Each DR as DataRow in DS.Tables(0).Rows
Dim URL as String = DR("Your_URL_Column_Name").ToString()
Dim Destination as String = "\\SERVERNAME\FolderName\"
My.Computer.Network.DownloadFile(URL, Destination & SubString(URL.LastIndexOf("/") + 1), "name", "password")
Next

This function will help you download a list of images to a specified local path
public void DownloadFiles(IEnumerable<string> urls, string path)
{
if (!System.IO.Directory.Exists(path))
System.IO.Directory.CreateDirectory(path);
System.Threading.Tasks.Parallel.ForEach(urls, url =>
{
using (var downloader = new WebClient())
{
var filePath = System.IO.Path.Combine(path, System.IO.Path.GetFileName(url));
downloader.DownloadFile(url,filePath);
}
});
}
You can use it similar to this:
var urlList= DS.Tables[0].Rows
.Cast<DataRow>()
.Select(x => x["YourColumnNameOfUrl"].ToString());
DownloadFiles(urlList,"C:\Directory\Of\Ur\Choice\");

Here is a small utility function to help you with your task
Function SaveRemoteImage(remoteImageUrl As String) As Integer
Try
Dim request = WebRequest.Create(remoteImageUrl)
Dim folderName = Server.MapPath("~/VB/Images/")
Using response As WebResponse = request.GetResponse()
Using stream As Stream = response.GetResponseStream()
Dim imageExtension = String.Empty
Select Case response.ContentType.ToLower
Case "image/bmp",
"image/x-bmp",
"image/x-ms-bmp"
imageExtension = ".bmp"
Case "image/jpeg"
imageExtension = ".jpeg"
Case "image/gif"
imageExtension = ".gif"
Case "image/png"
imageExtension = ".png"
Case Else
imageExtension = ".png"
End Select
'renaming image name as GUID to avoid conflicts
Dim imageName = Guid.NewGuid().ToString()
' Download the file
Dim destinationPath = String.Concat(
folderName,
imageName,
imageExtension)
Using tempFile = File.OpenWrite(destinationPath)
' Remark: if the file is very big read it in chunks
' to avoid loading it into memory
Dim buffer = New Byte(response.ContentLength - 1) {}
stream.Read(buffer, 0, buffer.Length)
tempFile.Write(buffer, 0, buffer.Length)
End Using
End Using
End Using
Return True
Catch ex As Exception
Return False
End Try
End Function
I am not using the WebClient method as we need the correct Image Content-Type to get the local files extension.
Now, get all ImageUrls as an IEnumerable(Of String) from the DataTable and call it like this
Dim images = table.AsEnumerable().
Select(Function(row) row.Field(Of String)("ImageUrl"))
For Each remoteImage In images
SaveRemoteImage(remoteImage)
Next
If you want some parallel programming magic, replace the For Each like this.
System.Threading.Tasks.Parallel.ForEach(images,
Function(remoteImage) SaveRemoteImage(remoteImage))

Related

Generate PDF in using windows form

I want to generate a PDF using windows form in the desktop application. I have readymade pdf design and I just want to feed data from database in that blank section of pdf for each user. (One type of receipt). Please guide me. I have searched but most of the time there is the solution in asp.net for the web application. I want to do in the desktop app. Here is my code I am able to fatch data from database and print in pdf. But main problem is trhat I have already designed pdf and I want to place data exactly at same field (ie name, Amount, date etc.)
using System;
using System.Windows.Forms;
using System.Diagnostics;
using PdfSharp;
using PdfSharp.Drawing;
using PdfSharp.Pdf;
using System.Data.SqlClient;
using System.Data;
using System.Configuration;
namespace printPDF
{
public partial class Form1 : Form
{
public Form1()
{
InitializeComponent();
}
private void button1_Click_1(object sender, EventArgs e)
{
try
{
string connetionString = null;
SqlConnection connection ;
SqlCommand command ;
SqlDataAdapter adapter = new SqlDataAdapter();
DataSet ds = new DataSet();
int i = 0;
string sql = null;
int yPoint = 0;
string pubname = null;
string city = null;
string state = null;
connetionString = "Data Source=EEVO-SALMAN\\MY_PC;Initial Catalog=;User ID=s***;Password=******";
// var connectionString = ConfigurationManager.ConnectionStrings["CharityManagement"].ConnectionString;
sql = "select NAME,NAME,uid from tblumaster";
connection = new SqlConnection(connetionString);
connection.Open();
command = new SqlCommand(sql, connection);
adapter.SelectCommand = command;
adapter.Fill(ds);
connection.Close();
PdfDocument pdf = new PdfDocument();
pdf.Info.Title = "Database to PDF";
PdfPage pdfPage = pdf.AddPage();
XGraphics graph = XGraphics.FromPdfPage(pdfPage);
XFont font = new XFont("Verdana", 20, XFontStyle.Regular );
yPoint = yPoint + 100;
for (i = 0; i <=ds.Tables[0].Rows.Count-1; i++)
{
pubname = ds.Tables[0].Rows[i].ItemArray[0].ToString ();
city = ds.Tables[0].Rows[i].ItemArray[1].ToString();
state = ds.Tables[0].Rows[i].ItemArray[2].ToString();
graph.DrawString(pubname, font, XBrushes.Black, new XRect(10, yPoint, pdfPage.Width.Point, pdfPage.Height.Point), XStringFormats.TopLeft);
graph.DrawString(city, font, XBrushes.Black, new XRect(200, yPoint, pdfPage.Width.Point, pdfPage.Height.Point), XStringFormats.TopLeft);
graph.DrawString(state, font, XBrushes.Black, new XRect(400, yPoint, pdfPage.Width.Point, pdfPage.Height.Point), XStringFormats.TopLeft);
yPoint = yPoint + 40;
}
string pdfFilename = "dbtopdf.pdf";
pdf.Save(pdfFilename);
Process.Start(pdfFilename);
}
catch (Exception ex)
{
MessageBox.Show(ex.ToString());
}
}
}
}
Instead of modifying the document, please create a new document and copy the pages from the old document to new document
sample code can be found here,
http://forum.pdfsharp.net/viewtopic.php?p=2637#p2637
Because modifying pdf is not recommended using 'PdfSharp' library. if you still want to edit you can use 'ISharp' library which needs a license.
Here is some VB.Net code I use to fill PDF forms. You need a PDF fillable form with form control names matching the SQL record field names.
It calls a routine Gen.GetDataTable() that just builds a typical DataTable. You could re-code to accept a pre-built Datatable as a parameter. Only the top row is processed. The code can be modified to work with a DataRow (.Table.Columns for column reference) or a DataReader.
Public Function FillPDFFormSQL(pdfMasterPath As String, pdfFinalPath As String, SQL As String, Optional FlattenForm As Boolean = True, Optional PrintPDF As Boolean = False, Optional PrinterName As String = "", Optional AllowMissingFields As Boolean = False) As Boolean
' case matters SQL <-> PDF Form Field Names
Dim pdfFormFields As AcroFields
Dim pdfReader As PdfReader
Dim pdfStamper As PdfStamper
Dim s As String = ""
Try
If pdfFinalPath = "" Then pdfFinalPath = pdfMasterPath.Replace(".pdf", "_Out.pdf")
Dim newFile As String = pdfFinalPath
pdfReader = New PdfReader(pdfMasterPath)
pdfStamper = New PdfStamper(pdfReader, New FileStream(newFile, FileMode.Create))
pdfReader.Close()
pdfFormFields = pdfStamper.AcroFields
Dim dt As DataTable = Gen.GetDataTable(SQL)
For i As Integer = 0 To dt.Columns.Count - 1
s = dt.Columns(i).ColumnName
If AllowMissingFields Then
If pdfFormFields.Fields.ContainsKey(s) Then
pdfFormFields.SetField(s, dt.Rows(0)(i).ToString.Trim)
Else
Debug.WriteLine($"Missing PDF Field: {s}")
End If
Else
pdfFormFields.SetField(s, dt.Rows(0)(i).ToString.Trim)
End If
Next
' flatten the form to remove editing options
' set it to false to leave the form open for subsequent manual edits
If My.Computer.Keyboard.CtrlKeyDown Then
pdfStamper.FormFlattening = False
Else
pdfStamper.FormFlattening = FlattenForm
End If
pdfStamper.Close()
If Not newFile.Contains("""") Then newFile = """" & newFile & """"
If Not PrintPDF Then
Process.Start(newFile)
Else
Dim sPDFProgramPath As String = INI.GetValue("OISForms", "PDFProgramPath", "C:\Program Files (x86)\Foxit Software\Foxit PhantomPDF\FoxitPhantomPDF.exe")
If Not IO.File.Exists(sPDFProgramPath) Then MsgBox("PDF EXE not found:" & vbNewLine & sPDFProgramPath) : Exit Function
If PrinterName.Length > 0 Then
Process.Start(sPDFProgramPath, "/t " & newFile & " " & PrinterName)
Else
Process.Start(sPDFProgramPath, "/p " & newFile)
End If
End If
Return True
Catch ex As Exception
MsgBox(ex.Message)
Return False
Finally
pdfStamper = Nothing
pdfReader = Nothing
End Try
End Function

SSIS 2015 Script task convert text file to UTF8 in C# or VB

I want to convert my resulting txt file into a UTF8 formatted file so I can load it into my Azure SQL DW via Polybase. It is required the source file be in UTF8.
MSDN has an "IO Streaming example" HERE works perfectly for a single job. I am trying to architect an SSIS solution for around 30 tables though. I believe using this method would cause a race condition where the PS script will be locked by 1 SSIS package when another SSIS package needs it.
I am a sql dev, not a .NET dev so please forgive me. How would one convert the above to an SSIS C# Script task assuming I know how to pass parameters into the Script task?
PowerShell Code from MSDN
#Static variables
$ascii = [System.Text.Encoding]::ASCII
$utf16le = [System.Text.Encoding]::Unicode
$utf8 = [System.Text.Encoding]::UTF8
$ansi = [System.Text.Encoding]::Default
$append = $False
#Set source file path and file name
$src = [System.IO.Path]::Combine("<MySrcFolder>","<MyUtf8stage>.txt")
#Set source file encoding (using list above)
$src_enc = $ascii
#Set target file path and file name
$tgt = [System.IO.Path]::Combine("<MyDestFolder>","<MyFinalstage>.txt")
#Set target file encoding (using list above)
$tgt_enc = $utf8
$read = New-Object System.IO.StreamReader($src,$src_enc)
$write = New-Object System.IO.StreamWriter($tgt,$append,$tgt_enc)
while ($read.Peek() -ne -1)
{
$line = $read.ReadLine();
$write.WriteLine($line);
}
$read.Close()
$read.Dispose()
$write.Close()
$write.Dispose()
Update
I found a similar post which I was able to tweak to my needs, I swear I searched high and low before posting. Anyway here is what IS working for me. If you see anyway to improve it please share:
public void Main()
{
//$Package::SourceSQLObject = tablename
//$Package::StageFile_DestinationFolderPath = rootpath eg "C:\temp\"
string path = (string)Dts.Variables["$Package::StageFile_DestinationFolderPath"].Value;
string name = (string)Dts.Variables["$Package::SourceSQLObject"].Value;
string from = Path.Combine(path, name) + ".csv";
string to = Path.ChangeExtension(from, "txt");
Dts.Log("Starting " + to.ToUpper(), 0, null);
using (StreamReader reader = new StreamReader(from, Encoding.ASCII, false, 10))
using (StreamWriter writer = new StreamWriter(to, false, Encoding.UTF8, 10))
{
while (reader.Peek() >= 0)
{
writer.WriteLine(reader.ReadLine());
}
}
Dts.TaskResult = (int)ScriptResults.Success;
Your code indicates that your are trying to convert an ASCII file to UTF-8 however that article also states the following:
As UTF-8 uses the same character encoding as ASCII PolyBase will also
support loading data that is ASCII encoded.
So my advice to you is to try the file first with Polybase, check for any conversion issues before you spend any time trying to convert the files.
var mySrcFolder = ""; // something from user variables?
var myUtf8stage = ""; // something from user variables?
var myFinalstage = ""; // something from user variables?
// Static variables
var ascii = System.Text.Encoding.ASCII;
var utf16le = System.Text.Encoding.Unicode;
var utf8 = System.Text.Encoding.UTF8;
var ansi = System.Text.Encoding.Default;
var append = false;
// Set source file path and file name
var src = System.IO.Path.Combine(
mySrcFolder,
String.Format("{0}.txt", myUtf8stage));
// Set source file encoding (using list above)
var src_enc = ascii;
// Set target file path and file name
var tgt = System.IO.Path.Combine(
mySrcFolder,
String.Format("{0}.txt", myFinalstage));
// Set target file encoding (using list above)
var tgt_enc = utf8;
using (var read = new System.IO.StreamReader(src, src_enc))
using (var write = new System.IO.StreamWriter(tgt, append, tgt_enc))
{
while (read.Peek() != -1)
{
var line = read.ReadLine();
write.WriteLine(line);
}
}
public void Main()
{
//$Package::SourceSQLObject = tablename
//$Package::StageFile_DestinationFolderPath = rootpath eg "C:\temp\"
string path = (string)Dts.Variables["$Package::StageFile_DestinationFolderPath"].Value;
string name = (string)Dts.Variables["$Package::SourceSQLObject"].Value;
string from = Path.Combine(path, name) + ".csv";
string to = Path.ChangeExtension(from, "txt");
Dts.Log("Starting " + to.ToUpper(), 0, null);
using (StreamReader reader = new StreamReader(from, Encoding.ASCII, false, 10))
using (StreamWriter writer = new StreamWriter(to, false, Encoding.UTF8, 10))
{
while (reader.Peek() >= 0)
{
writer.WriteLine(reader.ReadLine());
}
}
Dts.TaskResult = (int)ScriptResults.Success;

Overriding image issue

Here is my issue:
I'm trying to loop through folder get the files from the folder and save each file to an image and then to the DataBase but for some reason the length of the image is the same all the time. like it's not creating a new instance of an image.
Here is my code + comments:
Dim dba As New DBAccess
Dim folderName As String = String.Empty
Dim imageFileName As String = String.Empty
Dim ms1 As New MemoryStream()
Dim ds As DataSet = New DataSet
If m_IncidentCaseID > 0 Then
If Not String.IsNullOrEmpty(Sessions.GetKeyValueSessionFile(m_SessionID, "IRPicturesPath")) Then
m_IncidentPicturesPath = Convert.ToString(Sessions.GetKeyValueSessionFile(m_SessionID, "IRPicturesPath"))
End If
folderName = m_IncidentPicturesPath '!= Set the path of the folder.
'!= For Each file get the data from the DataBase: PictureID,PictureIndex,PictureFileName.
m_HashTableIRPicturesWriter = New Hashtable
m_DictionaryEntryIRPicturesWriter = New DictionaryEntry
Dim strArr As String() = Directory.GetFiles(folderName)
For Each filePath As String In strArr
ds = dba.GetPicturesIDFromPath(filePath, m_User.CompanyCode)
If Not ds Is Nothing Then
m_HashTableIRPicturesWriter.Add(ds.Tables(0).Rows(0).Item("PictureID").ToString(), filePath)
End If
Next
'!= We saved each file Path +PictrureID to Hashtable
'!== Loop through the hashtable and for each file in the folder create an image.
For Each filename As DictionaryEntry In m_HashTableIRPicturesWriter
Dim img As System.Drawing.Image = System.Drawing.Image.FromFile(filename.Value())
Dim bytes As Byte()
img.Save(ms1, System.Drawing.Imaging.ImageFormat.Jpeg)
bytes = ms1.ToArray()
'!=================================== Delete and Insert to the Temp_Table in the DB ==============================!
Dim dBConnection As String
dBConnection = Globals.GetConnectionStringMain(m_User.CompanyCode())
Dim connString As New SqlConnection(dBConnection)
'# First Delete the table from the IncidentID that we want to insert.
Dim sql1 As String = "Delete From Temp_Incident_Images Where PictureID =" & filename.Key()
Dim cmd1 As New SqlCommand(sql1, connString)
If connString.State = ConnectionState.Closed Then
connString.Open()
End If
cmd1.Parameters.Add(New SqlParameter("#IncidentID", m_IncidentCaseID))
cmd1.ExecuteNonQuery()
connString.Close()
If connString.State = ConnectionState.Closed Then
connString.Open()
End If
'# Second Inserst the PictureID to the Table.
Dim sql As String = "Insert Into Temp_Incident_Images(PictureID,IncidentID,IncidentImage) values (#PictureID,#IncidentID,#IncidentImage)"
Dim cmd As New SqlCommand(sql, connString)
cmd.Parameters.AddWithValue("#IncidentID", m_IncidentCaseID)
cmd.Parameters.AddWithValue("#PictureID", filename.Key())
Dim data As Byte() = ms1.GetBuffer() '!=When checking the Data it's same all the time.
Dim p As New SqlParameter("#IncidentImage", SqlDbType.Image)
p.Value = data
cmd.Parameters.Add(p)
Try
cmd.ExecuteNonQuery()
Catch ex As Exception
Throw New SystemException(ex.Message.ToString.Trim)
End Try
ms1.Close()
connString.Close()
img.Dispose()
Next
End If
How can I create a new instance of an image from this lines of code:
Dim img As System.Drawing.Image = System.Drawing.Image.FromFile(filename.Value())
Dim bytes As Byte()
img.Save(ms1, System.Drawing.Imaging.ImageFormat.Jpeg)
bytes = ms1.ToArray()
if you having image path issues with database here is simple code you can work with.
add file upload and a label or anything like this,
<asp:FileUpload id="FileUploadControl" runat="server" />
<asp:Label runat="server" id="StatusLabel" text="Upload status: " />
after that add a button which performs the any operation you want.
<asp:Button runat="server" class="btn btn-info pull-right" id="UploadButton" text="Upload" onclick="UploadButton_Click" />
inside the button add
Try
If FileUploadControl.PostedFile.ContentType = "image/jpeg" Then
If FileUploadControl.PostedFile.ContentLength < 102400 Then
Dim filename As String = Path.GetFileName(FileUploadControl.FileName)
FileUploadControl.SaveAs(Server.MapPath("~/ProductImages/") & filename)
StatusLabel.Text = "Upload status: File uploaded!"
Else
StatusLabel.Text = "Upload status: The file has to be less than 100 kb!"
End If
Else
StatusLabel.Text = "Upload status: Only JPEG files are accepted!"
End If
Catch ex As Exception
StatusLabel.Text = "Upload status: The file could not be uploaded. The following error occured: " + ex.Message
End Try
Please let me know if it solves your problem I can edit the code if you need any more help.

Send Multiple Documents To Printer

I have one Requirement in .net wpf.
There are some images in format of .gif or .jpg in a local folder.
I have prepared one List of string , to store file names
i want to send all images in a list to a printer in button click.
I have searched Google but for Print document we can give only one file PrintFileName.
But i want to give each file name in for each loop . any one can explain how is it possible?
Thanks..
question subject is look like wrong...
answer;
var filenames = Directory.EnumerateFiles(#"c:\targetImagePath", "*.*", SearchOption.AllDirectories)
.Where(s => s.EndsWith(".gif") || s.EndsWith(".jpg") || s.EndsWith(".bmp"));
foreach (var filename in filenames)
{
//use filename
}
Private Sub btnPrint_Click(sender As Object, e As RoutedEventArgs) Handles btnPrint.Click
Dim printDialog = New System.Windows.Controls.PrintDialog()
If printDialog.ShowDialog = False Then
Return
End If
Dim fixedDocument = New FixedDocument()
fixedDocument.DocumentPaginator.PageSize = New System.Windows.Size(printDialog.PrintableAreaWidth, printDialog.PrintableAreaHeight)
For Each p In _lablefilenames
Dim page As New FixedPage()
Dim info As System.IO.FileInfo = New FileInfo(p)
'If info.Extension.ToLower = ".gif" Then
' page.Width = fixedDocument.DocumentPaginator.PageSize.Height
' page.Height = fixedDocument.DocumentPaginator.PageSize.Width
'Else
page.Width = fixedDocument.DocumentPaginator.PageSize.Width
page.Height = fixedDocument.DocumentPaginator.PageSize.Height
'End If
Dim img As New System.Windows.Controls.Image()
' PrintIt my project's name, Img folder
'Dim uriImageSource = New Uri(p, UriKind.RelativeOrAbsolute)
'img.Source = New BitmapImage(uriImageSource)
Dim Bimage As New BitmapImage()
Bimage.BeginInit()
Bimage.CacheOption = BitmapCacheOption.OnLoad
Bimage.UriSource = New Uri(p)
If info.Extension.ToLower = ".gif" Then Bimage.Rotation += Rotation.Rotate90
Bimage.EndInit()
'img.Width = 100
'img.Height = 100
img.Source = Bimage
page.Children.Add(img)
Dim pageContent As New PageContent()
DirectCast(pageContent, IAddChild).AddChild(page)
fixedDocument.Pages.Add(pageContent)
Next
' Print me an image please!
printDialog.PrintDocument(fixedDocument.DocumentPaginator, "Print")
End Sub

Converting a file read VB code to c#

I need to convert a piece of code from VB to C#. what should I use in place of FileSystemObject and TextStream?
what the below code does is that it reads a file already present in a directory and adds the content of the file to the fields.
Private Sub Read_abc_File()
Dim FileSystem As FileSystemObject
Dim abcFile As TextStream
Dim abcLine As String, abcSection As String
Dim abcFilename As String
Const Read As Integer = 1
abcFilename = "abc.txt"
Set FileSystem = New FileSystemObject
If Not FileSystem.FileExists(abcFilename) Then
FileSystem = Null
Exit Sub
End If
Set abcFile = FileSystem.OpenTextFile(abcFilename, Read, False)
Do While abcFile.AtEndOfStream <> True
abcLine = abcFile.ReadLine
If abcLine > " " Then
If Left$(abcLine, 1) = "[" Then
abcSection = abcLine
Else
Select Case abcSection
Case "[Datafiles]"
DataFilename.AddItem abcLine
Case "[Locations]"
Location.AddItem abcLine
Case "[Formats]"
Format.AddItem abcLine
Case "[Categories]"
Category.AddItem abcLine
End Select
End If
End If
Loop
abcFile.Close
Set abcFile = Nothing
Set FileSystem = Nothing
End Sub
any suggestions/answers are appreciated.
Thanks!
Heres a code snippet to get you started, i think you should be able to complete the job.
using System;
using System.IO;
static void Main(string[] args)
{
string fileName = "abc.txt";
if (!File.Exists(fileName))
return;
using (FileStream file = File.OpenRead(fileName))
using (StreamReader reader = new StreamReader(file))
{
while (!reader.EndOfStream)
{
string line = reader.ReadLine();
}
}
}

Categories