I'm using this code:
Imports System.IO
Imports System.Net
Public Class sendftp
Public Function UploadFileToFtp(ByVal f As String, ByVal host As String, ByVal username As String, ByVal password As String, ByVal folderToUploadTo As String) As Boolean
Try
'create an FtpRequest object, holds the value of the path you are trying to reach
Dim ftpRequest As FtpWebRequest = DirectCast(FtpWebRequest.Create(New Uri(host & "/" & Path.GetFileName(folderToUploadTo))), FtpWebRequest)
'pass in our login credentials
ftpRequest.Credentials = New NetworkCredential(username, password)
'set the method to Upload, since we're uploading a file
ftpRequest.Method = WebRequestMethods.Ftp.UploadFile
'don't use passive mode
ftpRequest.UsePassive = True
'unless we're uploading a file like an image
'we need to set this to false as we're not uploading
'binary data
ftpRequest.UseBinary = True
'set KeepAlive to false
ftpRequest.KeepAlive = False
'now create a new FileStream, then open the file we're uploading
'this allows us to get the size of the file for our buffer
Dim stream As FileStream = File.OpenRead(f)
'create a byte[] array buffer the size of the file
'we're uploading
Dim buffer As Byte() = New Byte(stream.Length - 1) {}
'read in our file into the FileStream
stream.Read(buffer, 0, buffer.Length)
'close the FileStream
stream.Close()
'create a new stream, this will be used to write to the
'FTP server
Dim requestStream As Stream = ftpRequest.GetRequestStream()
'write the data to the FTP server
requestStream.Write(buffer, 0, buffer.Length)
'close the stream
requestStream.Close()
'since we made it this far return true
Return True
Catch ex As Exception
'something went wront so let the user know
MessageBox.Show("Error uploading file: " + ex.Message, "Upload Error")
'return false
Return False
End Try
End Function
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
UploadFileToFtp("C:\file.txt", "ftp://ftp.drivehq.com", "**user**", "**password**", "new.txt")
End Sub
End Class
And it works.
However I would like to use my FileZilla Server, so I edit the ftp url:
UploadFileToFtp("C:\file.txt", "ftp://localhost", "**user**", "**password**", "new.txt")
but I get this error : ?
The remote server returned an error:(550) File unavailable (e.g., file not found, no access).
I can't figure it out, any ideas?
Turned out to be permission that I fixed by going to ftp server settings... sorry for my inconvenience
Related
i'm using the above code to run a form with a tcplistener.
when the tcplistener recevie data from the client i need to write the data in in label1.text
i have tryed to use Shown instead of Load the form is showed but it the label text doesn't change.
How can i resolve this? any help will be appreciated.
thank you
Public Class Form1
Private Sub Form1_Load(sender As Object, e As EventArgs) Handles MyBase.Load
TcpServer()
End Sub
Shared Sub TcpServer()
Dim server As TcpListener
server = Nothing
Try
Dim port As Int32 = 4000
Dim localAddr As IPAddress = IPAddress.IPv6Any 'IPAddress.Parse("192.168.61.9") 'IPAddress.Any
server = New TcpListener(localAddr, port)
server.Start()
Dim bytes(1024) As Byte
Dim data As String = Nothing
While True
Console.WriteLine("Waiting for a connection... ")
Dim client As TcpClient = server.AcceptTcpClient()
Console.WriteLine("Connected!")
data = Nothing
Dim stream As NetworkStream = client.GetStream()
Dim i As Int32
' Loop to receive all the data sent by the client.
i = stream.Read(bytes, 0, bytes.Length)
While (i <> 0)
' Translate data bytes to a ASCII string.
data = System.Text.Encoding.ASCII.GetString(bytes, 0, i)
Form1.Label1.Text = data
' Process the data sent by the client.
'data = data.ToUpper()
data = "aaa"
Dim msg As Byte() = System.Text.Encoding.ASCII.GetBytes(data)
' Send back a response.
stream.Write(msg, 0, msg.Length)
Console.WriteLine("Sent: {0}" + data)
i = stream.Read(bytes, 0, bytes.Length)
End While
' Shutdown and end connection
client.Close()
Form1.Refresh()
End While
Catch e As SocketException
MsgBox("SocketException: {0}", e.ToString)
Finally
server.Stop()
End Try
Console.WriteLine(ControlChars.Cr + "Hit enter to continue....")
Console.Read()
End Sub 'Main
Run TcpServer() on a new thread, or make use of BackGroundWorker Control which is part of winForms controls.
I am trying to implement a Telnet client in VB.NET. I am following this code as example:
The program I'm implementing works as follows:
I click the button "Open Telnet" to open the Telnet session.
I write an instruction (string) in the text box on the left and then I click on Button1 to send the message to a Telnet server (an electronic board with an embedded Ethernet port).
The answer sent by the Telnet server is displayed in the text box on the left.
The problem I'm having with both the example and the implementation I'm doing is that the messages are displayed delayed. For example, if I send the string 1FFFFFF + vbCrLf I am supposed to receive a message from the server saying Unknown HMI code!. I have checked with Wireshark that the message is sent by the Telnet server just after I sent the instruction with the VB.NET program but it is shown in the text box on the right only if I click Button1 a second time (no matter what is written in the text box on the left).
Could you please tell me if there is something I'm missing in the code?
Below is my code:
Imports System
Imports System.IO
Imports System.Net.Sockets
Imports System.Security.Cryptography.X509Certificates
Imports System.Text
Imports System.Threading
Imports System.Net.Http
Imports System.Net.Security
Imports System.Net.IPAddress
Imports System.Net
Public Class Form1
' Create a TcpClient.
Dim client As New TcpClient
Dim stream As NetworkStream
' Function to write/read a TCP stream.
Shared Sub Connect(server As [String], message As [String])
Try
' Translate the passed message into ASCII and store it as a Byte array.
Dim data As [Byte]() = System.Text.Encoding.ASCII.GetBytes(message)
' Send the message to the connected TcpServer.
Form1.stream.Write(data, 0, data.Length)
Console.WriteLine("Sent: {0}", message)
' Buffer to store the response bytes.
data = New [Byte](256) {}
' String to store the response ASCII representation.
Dim responseData As [String] = [String].Empty
' Read the first batch of the TcpServer response bytes.
Dim bytes As Int32 = Form1.stream.Read(data, 0, data.Length)
responseData = System.Text.Encoding.ASCII.GetString(data, 0, bytes)
Console.WriteLine("Received: {0}", responseData)
Form1.TelnetRx.Text += responseData + vbCrLf
Form1.TelnetRx.Refresh()
Catch e As ArgumentNullException
Console.WriteLine("ArgumentNullException: {0}", e)
Catch e As SocketException
Console.WriteLine("SocketException: {0}", e)
End Try
Console.WriteLine(ControlChars.Cr + " Press Enter to continue...")
Console.Read()
End Sub
' Function to open a Telnet session.
Public Function OpenTelnetSession(server As String, Port As Int32) As Boolean
Dim ipAddress As IPAddress = Parse(server)
client.Connect(ipAddress, Port)
stream = Me.client.GetStream()
Return True
End Function
' Button to send a message.
Private Sub Button1_Click(sender As Object, e As EventArgs) Handles Button1.Click
Connect("192.168.8.110", TCP_Order.Text + vbCrLf)
End Sub
' Button to open the Telnet session.
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles OpenTelnet.Click
OpenTelnetSession("192.168.8.110", 10001)
End Sub
' Button to close the Telnet session.
Private Sub CloseTelnet_Click(sender As Object, e As EventArgs) Handles CloseTelnet.Click
End Sub
End Class
That because you are not reading the entire buffer of the response, you are just taking 256 bytes from it:
data = New [Byte](256) {} ' <-
Also you have to free the resource by closing the streams and the TcpClient once you receive the response. Always create the disposable objects by the Using statement to guarantee that.
Synchronous Example
The example below connects to an endpoint in synchronous blocking mode, the caller thread is blocked until a response is returned from the endpoint or an exception is thrown (connection timeout for example.)
Private Function Connect(server As String, port As Integer, Msg As String) As String
Using client As New TcpClient(server, port),
netStream = client.GetStream,
sr = New StreamReader(netStream, Encoding.UTF8)
Dim msgBytes = Encoding.UTF8.GetBytes(Msg)
netStream.Write(msgBytes, 0, msgBytes.Length)
Return sr.ReadToEnd
End Using
End Function
and the caller:
Private Sub TheCaller()
Dim resp As String = Nothing
Try
Dim server = "192.168.8.110"
Dim port = 10001
Dim msg = $"1FFFFFF{ControlChars.CrLf}{ControlChars.CrLf}"
resp = Connect(server, port, msg)
Catch ex As ArgumentNullException
resp = ex.Message
Catch ex As SocketException
resp = ex.SocketErrorCode.ToString
Catch ex As Exception
resp = ex.Message
Finally
If resp IsNot Nothing Then
UpdateStatus(resp)
End If
End Try
End Sub
Asynchronous Example
You may want to use an asynchronous operation since you are developing a WinForms application, and I don't think you want to block the UI thread. Here you need to call the Async methods of the TcpClient and the read/write streams:
Private Async Function ConnectAsync(server As String,
port As Integer, msg As String) As Task(Of String)
Using client As New TcpClient
Await client.ConnectAsync(server, port)
Using netStream = client.GetStream,
sw = New StreamWriter(netStream, Encoding.UTF8) With {.AutoFlush = True },
sr = New StreamReader(netStream, Encoding.UTF8)
Await sw.WriteLineAsync(msg)
Return Await sr.ReadToEndAsync()
End Using
End Using
End Function
and an Async caller:
Private Async Sub TheCaller()
Dim resp As String = Nothing
Try
Dim server = "192.168.8.110"
Dim port = 10001
Dim msg = $"1FFFFFF{ControlChars.CrLf}{ControlChars.CrLf}"
resp = Await ConnectAsync(server, port, msg)
Catch ex As ArgumentNullException
resp = ex.Message
Catch ex As SocketException
resp = ex.SocketErrorCode.ToString
Catch ex As Exception
resp = ex.Message
Finally
If resp IsNot Nothing Then
UpdateStatus(resp)
End If
End Try
End Sub
The UpdateStatus in the code snippets is just a method to append the responses into a TextBox..
Private Sub UpdateStatus(txt As String)
StatusTextBox.AppendText(txt)
StatusTextBox.AppendText(ControlChars.NewLine)
End Sub
I would like to use a visual basic desktop app to upload a file to Google Drive. The main purpose of the app does much more, but this is a time-saving feature I need to add
I have downloaded the NuGet for Google.Apis.Drive.v2 and have added the following code:
Imports Google.Apis.Auth.OAuth2
Imports Google.Apis.Drive.v2
Imports Google.Apis.Drive.v2.Data
Imports Google.Apis.Services
I have a button to call my code:
Private Sub Button4_Click(sender As Object, e As EventArgs) Handles Button4.Click
CreateService()
UploadFile(myFile)
End Sub
And then I have code to Create the Service and Upload the File:
Private Sub CreateService()
Dim ClientId = "My ClientID copied from Google"
Dim ClientSecret = "My Client Secret"
Dim MyUserCredential As UserCredential = _
GoogleWebAuthorizationBroker.AuthorizeAsync(New ClientSecrets() _
With {.ClientId = ClientId, .ClientSecret = ClientSecret}, _
{DriveService.Scope.Drive}, "user", CancellationToken.None).Result
Service = New DriveService(New BaseClientService.Initializer() _
With {.HttpClientInitializer = MyUserCredential, .ApplicationName = "SiteVisitTool"})
End Sub
Private Sub UploadFile(FilePath As String)
Me.Cursor = Cursors.WaitCursor
If Service.ApplicationName <> "SiteVisitTool" Then CreateService()
Dim TheFile As New Google.Apis.Drive.v2.Data.File
TheFile.Title = "Deliverables"
TheFile.Description = "Site Visit data for Google forms"
TheFile.MimeType = "text/csv"
Dim ByteArray As Byte() = System.IO.File.ReadAllBytes(FilePath)
Dim Stream As New System.IO.MemoryStream(ByteArray)
Dim UploadRequest As FilesResource.InsertMediaUpload = Service.Files.Insert(TheFile, Stream, TheFile.MimeType)
Me.Cursor = Cursors.Default
MsgBox("Upload Finished")
End Sub
The code runs and I get the message box that the upload has finished. I have checked Drive and the file doesn't exist. Sometimes I'm prompted for the account I want to use and then I have to activate it, but I always get the message that it as uploaded. Highly frustrated!
"SiteVisitTool" is the Project name on Google.
Should this just be going to the Root folder of Drive?
Also, if we can get this worked out, I'd like to follow-up and save it to a specific folder.
This turned out to be a simple fix. Apparently the website I got this solution from was missing the upload line. So after you create your Upload request, you need to tell it to upload.
Dim UploadRequest As FilesResource.InsertMediaUpload = Service.Files.Insert(TheFile, Stream, TheFile.MimeType)
UploadRequest.Upload()
As for specifying a folder to upload it to, I added where I set the properties of TheFile:
TheFile.Parents = New List(Of ParentReference)() From {
New ParentReference() With {
.Id = sFolderID
}
}
when I write to my log file I sometimes get access to log path is denied C:/app/log.log
Here is my code:
Private filePath As String
Private fileStream As FileStream
Private streamWriter As StreamWriter
Public Sub OpenFile()
Dim strPath As String
strPath = My.Application.Info.DirectoryPath + "\log.log"
If System.IO.File.Exists(strPath) Then
fileStream = New FileStream(strPath, FileMode.Append, FileAccess.Write)
Else
fileStream = New FileStream(strPath, FileMode.Create, FileAccess.Write)
End If
streamWriter = New StreamWriter(fileStream)
End Sub
Public Sub WriteLog(ByVal strComments As String)
OpenFile()
streamWriter.WriteLine(Date.Now.ToString & " " & strComments)
CloseFile()
End Sub
Public Sub CloseFile()
streamWriter.Close()
fileStream.Close()
End Sub
Is there anyway to make this use admin permissions or fix this issue? It only happens sometimes, and I'm not sure why it happens, but if I delete the log.log file the application can write to log again. Very weird.
You are calling your function WriteLog from multiple threads asynchronously, you should protect this function for example with a mutex.
I want to make a VB.NET software in which we can select folders and add them in a listbox. These folders and their contents are to be uploaded to a FTP site at a certain amount of time. My question is that what's the code to upload folders and its contents to FTP site. The listbox only contains the main directory locations. There maybe multiple directories in the listbox. Button 3 is the uploadnow button which later on I will connect to the timer. Button 2 is for selecting the directories.
So far I have achieved this:
Imports System.IO
Public Class SYNC
Private Sub Button2_Click(sender As Object, e As EventArgs) Handles Button2.Click
Dim dialog = New FolderBrowserDialog()
Dim dir As String
dialog.SelectedPath = Application.StartupPath
If DialogResult.OK = dialog.ShowDialog() Then
dir = dialog.SelectedPath
ListBox1.Items.Add(Path.GetFileName(dir))
End If
End Sub
Private Sub Button3_Click(sender As Object, e As EventArgs) Handles Button3.Click
End Sub
End Class
The WinSCP .NET assembly has the recursive transfer built-in.
Use the Session.PutFiles method like:
' Setup session options
Dim mySessionOptions As New SessionOptions
With mySessionOptions
.Protocol = Protocol.Ftp
.HostName = "example.com"
.UserName = "user"
.Password = "mypassword"
End With
Using mySession As Session = New Session
' Connect
mySession.Open(mySessionOptions)
' Upload files
mySession.PutFiles("d:\foldertoupload\*", "/home/user/").Check()
End Using
See a full example.
Note that the Session.PutFiles (and the assembly overall) has synchronous interface (calls are blocking). So you need to execute the code from a separate thread, not from the GUI thread. Otherwise your interface will be unresponsive, while the transfer is proceeding.
To provide a progress feedback to the user, use the Session.FileTransferProgress event and the FileTransferProgressEventArgs.OverallProgress property.
(I'm the author of WinSCP)
You'll need to use the System.Net.FtpWebRequest class.
This is an untested-by-me example I found here (modified to use Using statements):
http://www.digitalcoding.com/Code-Snippets/VB/Visual-Basic-Code-Snippet-Upload-file-to-FTP-Server.html
''' <summary>
''' Methods to upload file to FTP Server
''' </summary>
''' <param name="_FileName">local source file name</param>
''' <param name="_UploadPath">Upload FTP path including Host name</param>
''' <param name="_FTPUser">FTP login username</param>
''' <param name="_FTPPass">FTP login password</param>
Public Sub UploadFile(ByVal _FileName As String, ByVal _UploadPath As String, ByVal _FTPUser As String, ByVal _FTPPass As String)
Dim _FileInfo As New System.IO.FileInfo(_FileName)
' Create FtpWebRequest object from the Uri provided
Dim _FtpWebRequest As System.Net.FtpWebRequest = CType(System.Net.FtpWebRequest.Create(New Uri(_UploadPath)), System.Net.FtpWebRequest)
' Provide the WebPermission Credintials
_FtpWebRequest.Credentials = New System.Net.NetworkCredential(_FTPUser, _FTPPass)
' By default KeepAlive is true, where the control connection is not closed
' after a command is executed.
_FtpWebRequest.KeepAlive = False
' set timeout for 20 seconds
_FtpWebRequest.Timeout = 20000
' Specify the command to be executed.
_FtpWebRequest.Method = System.Net.WebRequestMethods.Ftp.UploadFile
' Specify the data transfer type.
_FtpWebRequest.UseBinary = True
' Notify the server about the size of the uploaded file
_FtpWebRequest.ContentLength = _FileInfo.Length
' The buffer size is set to 2kb
Dim buffLength As Integer = 2048
Dim buff(buffLength - 1) As Byte
' Opens a file stream (System.IO.FileStream) to read the file to be uploaded
Using _FileStream As System.IO.FileStream = _FileInfo.OpenRead()
Try
' Stream to which the file to be upload is written
Using _Stream As System.IO.Stream = _FtpWebRequest.GetRequestStream()
' Read from the file stream 2kb at a time
Dim contentLen As Integer = _FileStream.Read(buff, 0, buffLength)
' Till Stream content ends
Do While contentLen <> 0
' Write Content from the file stream to the FTP Upload Stream
_Stream.Write(buff, 0, contentLen)
contentLen = _FileStream.Read(buff, 0, buffLength)
Loop
' Close the file stream and the Request Stream
_Stream.Close()
_Stream.Dispose()
_FileStream.Close()
_FileStream.Dispose()
End Using
Catch ex As Exception
MessageBox.Show(ex.Message, "Upload Error", MessageBoxButtons.OK, MessageBoxIcon.Error)
End Try
End Using
End Sub