WWW fileupload using VB.NET or Access/VBA - vb.net

I would like to ask if there's a possibility to upload files to a webserver or an ftpserver using VB.NET or Access/VBA.
I think if there are possibilities - VB.NET is more powerful than Access/VBA, is that right?
Are there any chances using webservices?
And FTP? I think there must be a chance to copy files using VB.NET or Access via FTP ...
Is there anyone who could help me?
Thomas

Here is how you would do it using FTP:
Dim ftpRequest As System.Net.FtpWebRequest = DirectCast(System.Net.WebRequest.Create("ftp://ftp.myserver.com/foo.txt"), System.Net.FtpWebRequest)
ftpRequest.Credentials = New System.Net.NetworkCredential("username", "password")
ftpRequest.Method = System.Net.WebRequestMethods.Ftp.UploadFile
Dim myFile() As Byte = System.IO.File.ReadAllBytes("C:\somefile.txt")
Using ftpStream As System.IO.Stream = ftpRequest.GetRequestStream()
ftpStream.Write(myFile, 0, myFile.Length)
ftpStream.Close()
End Using

Related

delete Sharepoint file using Script Task

I need to delete a Sharepoint file using the Script Task from SSIS. In Visual Basic, I've tried using the SPListItemCollection with imports Microsoft.Sharepoint but it doesn't recognize the namespace. I didn't find lots of threads on this subject or what I've found wasn't related with script task, so any help will be really appreciated. Many thanks
Update based on #Hadi answer
Thanks Hadi for your answer. I've given up the idea of using SPListCollection as it seems too complicated. Instead I'm trying to delete the file after it is downloaded from Sharepoint to the local folder. I would need help at the line that actually deletes the file. Here is the code:
Public Sub Main()
Try
' get location of local folder
Dim dir As DirectoryInfo = New DirectoryInfo(Dts.Variables("DestP").Value.ToString())
If dir.Exists Then
' Create the filename for local storage
Dim file As FileInfo = New FileInfo(dir.FullName & "\" & Dts.Variables("FileName").Value.ToString())
If Not file.Exists Then
' get the path of the file to download
Dim fileUrl As String = Dts.Variables("SHP_URL").Value.ToString()
If fileUrl.Length <> 0 Then
Dim client As New WebClient()
If Left(fileUrl, 4).ToLower() = "http" Then
'download the file from SharePoint
client.Credentials = New System.Net.NetworkCredential(Dts.Variables("$Project::UserN").Value.ToString(), Dts.Variables("$Project::Passw").Value.ToString())
client.DownloadFile(fileUrl.ToString() & "/" & Dts.Variables("FileName").Value.ToString(), file.FullName)
Else
System.IO.File.Copy(fileUrl.ToString() & Dts.Variables("FileName").Value.ToString(), file.FullName)
End If
'delete file from Sharepoint
client.(fileUrl.ToString() & "/" & Dts.Variables("FileName").Value.ToString(), file.FullName).delete()
Else
Throw New ApplicationException("EncodedAbsUrl variable does not contain a value!")
End If
End If
Else
Throw New ApplicationException("No ImportFolder!")
End If
Catch ex As Exception
Dts.Events.FireError(0, String.Empty, ex.Message, String.Empty, 0)
Dts.TaskResult = ScriptResults.Failure
End Try
Dts.TaskResult = ScriptResults.Success
End Sub
Update 1 - Delete using FtpWebRequest
You cannot delete file using WebClient class. You can do that using FtpWebRequest class. And send a WebRequestMethods.Ftp.DeleteFile request as mentioned in the link below:
How To Delete a File From FTP Server in C#
It should work with Sharepoint also.
Here is the function in VB.NET
Private Function DeleteFile(ByVal fileName As String) As String
Dim request As FtpWebRequest = CType(WebRequest.Create(fileUrl.ToString() & "/" & fileName), FtpWebRequest)
request.Method = WebRequestMethods.Ftp.DeleteFile
request.Credentials = New NetworkCredential(Dts.Variables("$Project::UserN").Value.ToString(), Dts.Variables("$Project::Passw").Value.ToString())
Using response As FtpWebResponse = CType(request.GetResponse(), FtpWebResponse)
Return response.StatusDescription
End Using
End Function
You should replace the following line:
client.(fileUrl.ToString() & "/" & Dts.Variables("FileName").Value.ToString(), file.FullName).delete()
With
DeleteFile(Dts.Variables("FileName").Value.ToString())
Also you may use the following credentials:
request.Credentials = System.Net.CredentialCache.DefaultNetworkCredentials;
References
How to pass credentials to httpwebrequest for accessing SharePoint Library
How To Delete a File From FTP Server in C#
Downloading all files in a FTP folder and then deleting them
Deleting file from FTP in C#
How To Delete a File From FTP Server in C#
Initial Answer
I was searching for a similar issue from a while, it looks like you cannot delete a Sharepoint file in SSIS using a File System Task or Execute Process Task, the only way is using a Script Task. There are many links online describing this process such as:
how to delete or remove only text files from share point in C# or SSIS script?
Fastest way to delete all items with C#
Deleting files programatically
Deleting all the items from a large list in SharePoint
Concerning the problem that you have mentioned, i think you should make sure that Microsoft.Sharepoint.dll is added as a reference inside the Script Task. If so try using Microsoft.Sharepoint.SPListItemCollection instead of SPListItemCollection.
Thanks #Hadi for your help.
For me it didn't work with FTPWebResponse.
It worked with HttpWebRequest. Here is the script:
Dim request As System.Net.HttpWebRequest = CType(WebRequest.Create(fileUrl.ToString() & "/" & Dts.Variables("FileName").Value.ToString()), HttpWebRequest)
request.Credentials = New System.Net.NetworkCredential(Dts.Variables("$Project::UserN").Value.ToString(), Dts.Variables("$Project::Passw").Value.ToString())
request.Method = "DELETE"
Dim response As System.Net.HttpWebResponse = CType(request.GetResponse(), HttpWebResponse)

VB.Net FTP read of dynamically generated file where FTPGetFileSize is not supported

I've been struggling with trying to read the configuration files on a device via FTP. The files are generated dynamically when the FTP request is sent, and the device does not support the FTPGetFileSize command.
I've lost count of the number of examples from the Web that I've tried in an attempt to solve this. Part of the problem is likely due to my inexperience with file streams. So, I'm looking for a kind soul that might be able to provide some insight.
In the code below, I'm trying two different methods. The first is a straight read of the entire file, the second attempts to control the read based whether there is anything coming in over the stream.
Both methods work on other devices that support the FTPGetFileSize command. But neither method works for this device.
Project form
Imports are:
Imports System.Net
Imports System.IO
Imports System.Text
The cmdGet_Click event code looks like this:
Dim sLocal_Path As String = "C:\Temp\FTP_Test\" + txtIPAddress.Text + "\"
System.IO.Directory.CreateDirectory(sLocal_Path)
' Complete the local path
sLocal_Path += txtFileName.Text
If System.IO.File.Exists(sLocal_Path) Then
System.IO.File.Delete(sLocal_Path) ' Make sure we don't have a collision.
End If
' Set up the Remote Path.
Dim sRemote_Path As String = "ftp://" + txtIPAddress.Text + "/gen:" + txtFileName.Text
Dim request As FtpWebRequest = CType(WebRequest.Create(sRemote_Path), FtpWebRequest)
request.Method = WebRequestMethods.Ftp.DownloadFile
request.Credentials = New NetworkCredential(FTP_User, FTP_Password)
request.UsePassive = True
request.Timeout = 15000
request.UseBinary = False
Dim response As FtpWebResponse = CType(request.GetResponse(), FtpWebResponse)
Dim responseStream As Stream = response.GetResponseStream()
Dim reader As StreamReader = New StreamReader(responseStream)
Dim writeFile As StreamWriter = New StreamWriter(sLocal_Path)
If RadioReadToEnd.Checked Then
' Write the FTP stream to the target file
writeFile.Write(reader.ReadToEnd()) ' works with static files.
Else
' Write the FTP stream as long as we have data coming in.
Dim ByteCount As Integer = 0
Threading.Thread.Sleep(500)
While Not (reader.Peek() = -1)
ByteCount += 1
If ByteCount > 4095 Then ' Go up for air after every block.
ByteCount = 0 ' Reset the byte counter for the next block.
Application.DoEvents()
End If
writeFile.Write(Chr(reader.Read))
End While
End If
reader.Close()
reader.Dispose()
writeFile.Close()
writeFile.Dispose()
responseStream.Close()
responseStream.Dispose()
Note that I put a delay in just before the While Loop in the hopes that maybe something would show up in the stream to keep the loop from terminating. Apparently I need some way to prime the pump.
Edit: The DOS FTP Get works fine. My assumption is that it has some way to get around the FTPGetFileSize not being supported. Is there a way to get the WebClient FTP Methods to do the same thing with a dynamically generated file?
I need a nudge (okay, a kick) in the right direction. Any suggestions are greatly appreciated!
It is now working! The problem turned out to be a missing '/' at the root of the path.
This particular device has a drive reference in it's path that other devices my routine talks to did not have. So, between that and the error being thrown regarding the file size, I was put off of the scent.
Thanks to Martin Prikryl's comment about showing a log, I went off to create a Wireshark recording, and that's when I noticed the missing slash when I compared it to the DOS FTP Get recording. So, while I'm a little red-faced, I hope my experience helps someone else who runs into a similar problem. But mostly, I'm very relieved that I did not have to go the route of writing an FTP Client that dealt with raw commands such as POST and RETR! The WebClient tools are now working very well for this application.

WebClient.UploadData "The underlying connection was closed"

I'm trying to upload a file from an FTP site to Basecamp using the Basecamp API. I'm using a simple console application. Here's my code:
Try
Dim accountID As String = ConfigurationManager.AppSettings("BaseCampID")
Dim projectID As Integer = 9999999
Dim folderName As String = "XXXXX/XXXXX"
Dim fileName As String = "XXX.zip"
'The URL to access the attachment method of the API
Dim apiURL = String.Format("https://basecamp.com/{0}/api/v1/projects/{1}/attachments.json", accountID, projectID)
'Get the file from the FTP server as a byte array
Dim fileBytes As Byte() = GetFileBytes(String.Format("{0}\\{1}", folderName, fileName))
'Initialize the WebClient object
Dim client As New WebClient()
client.Headers.Add("Content-Type", "application/zip")
'Need to provide a user-agent with a URL or email address
client.Headers.Add("User-Agent", "Basecamp Upload (email#email.com)")
'Keep the connection alive so it doesn't close
client.Headers.Add("Keep-Alive", "true")
'Provide the Basecamp credentials
client.Credentials = New NetworkCredential("username", "password")
'Upload the file as a byte array to the API, and get the response
Dim responseStr As Byte() = client.UploadData(apiURL, "POST", fileBytes)
'Convert the JSON response to a BaseCampAttachment object
Dim attachment As BaseCampAttachment
attachment = JSonHelper.FromJSon(Of BaseCampAttachment)(Encoding.Default.GetString(responseStr))
Catch ex As Exception
Console.WriteLine(ex.Message)
Finally
Console.ReadLine()
End Try
But whenever it calls client.UploadData, I get the error message "The underlying connection was closed: The connection was closed unexpectedly." I ran into this issue earlier and thought I solved it by adding the "Keep-Alive" header, but it's not working anymore. The API works if I upload a local file with client.UploadFile, but I'd like to just upload the file from they byte array from the FTP rather than downloading the file locally then uploading it to Basecamp.
Any thoughts would be greatly appreciated. Thanks!
I never figured out what was wrong with the WebClient call, but I ended up using a Basecamp API wrapper from https://basecampwrapper.codeplex.com. That wrapper uses HTTPRequest and HTTPResponse instead of WebClient.UploadData. It's also much easier to just use that wrapper than to try writing my own code from scratch.

VB.NET (WebRequest Authentication Issue)

I'm new to WebRequest authentication and have been researching how to authenticate w/ a couple websites to pull some excel data from them. Couple things I'm confused about is
a.) how to properly read a log from Fiddler (using this to pick up get/post data from the website authentication)
b.) how do use the data from Fiddler to program the VB.NET WebRequest properly.
I've been able to authenticate w/ websites that use simple authentication HTTPS, but any site that does any redirects/REST/cookie auth I'm lost...
Let me know if I can provide anymore detail.
Dim req As Net.HttpWebRequest = Net.WebRequest.Create(Url)
If Not Login = Nothing AndAlso Not Password = Nothing Then
Dim myCache As New System.Net.CredentialCache()
myCache.Add(New Uri(Url), "Basic", New System.Net.NetworkCredential(Login, Password))
req.Credentials = myCache
End If
Dim sr As New StreamReader(req.GetResponse().GetResponseStream())
Dim ss as string = sr.ReadToEnd
'Save it as excel & close stream
sr.Close()

Getting a PDF from WCF to WCF

Okay, here's what I have...
On one server, a WCF hosted in IIS. This one handles a bunch of stuff for an ASP.NET application which resides on the same server (mostly db calls). In the ASP app, there's an embedded iFrame which contains a PDF document viewer.
On another server, a WCF hosted in a Windows service. This one handles calls from the first WCF and kicks off a third-party document program which generates PDF files. For now, I have a dummy PDF file sitting on the C:\ drive to play with.
My mission: To somehow have a function in WCF #2 return a copy of the PDF document to WCF #1, which will save it to the local ASP application directory, so the embedded viewer can display it to a user.
So far I've tried having WCF #2 return a FileStream object but no luck there. I guess that's a big no-no in the WCF world (I'm a noob).
I have no idea how to accomplish this, most of my efforts are proving futile. How would YOU handle this? Anyone?
Thanks!
Have WCF2 take the PDF and return it as a byte array:
// fs is your FileStream
byte[] Data = new byte[fs.Length];
fs.Read(Data,0,fs.Length);
WCF1 calls WCF2 and reads the byte array, then saves it to disk
FileStream fs = new FileStream(fileName, FileMode.Create, FileAccess.ReadWrite);
BinaryWriter bw = new BinaryWriter(fs);
bw.Write(buff);
bw.Close();
Thanks, Jason -- I did something similar. Thought I'd post for the next guy:
WCF #2:
Public Function GetPDF_Byte() As Byte() Implements IService1.GetPDF_Byte
Dim fs As New FileStream("C:\211LD.pdf", FileMode.Open, FileAccess.Read)
Dim ImageData As Byte() = New Byte(fs.Length - 1) {}
fs.Read(ImageData, 0, System.Convert.ToInt32(fs.Length))
fs.Close()
GetPDF_Byte = ImageData
End Function
And, WCF #1 which calls #2 and writes the file to disk:
Sub Main
Dim WCF As New ServiceReference1.Service1Client
Dim ByteData As Byte()
Dim oFileStream As System.IO.FileStream
ByteData = WCF.GetPDF_Byte
oFileStream = New System.IO.FileStream("C:\NewPDF.pdf", FileMode.Create)
oFileStream.Write(ByteData, 0, ByteData.Length)
oFileStream.Close()
End Sub
Hope that can help someone else!