Avatar billede jens_k Nybegynder
07. januar 2005 - 10:41 Der er 29 kommentarer og
1 løsning

Overførsel af filer/mapper til FTP Server. del 2 (diffentialt)

Hej,

Som i kan se her: http://www.eksperten.dk/spm/576941

Har jeg fået lavet et lille program som kan overfører nogle filer til en FTP server. Jeg bruger det til at tage backup af mine filer, men nogle af mine filer fylder meget, og bliver sjældent ændret, så det ville være rart hvis man kunne lave noget diffrential backup, så den kun tager de filer som er ændret i forhold til dem som ligger på serveren.

Hvordan får jeg det lavet ?

Mvh

Jens_K
Avatar billede arne_v Ekspert
07. januar 2005 - 22:17 #1
Tiden på den lokale fil er nem: File GetCreationTime eller File GetLastWriteTime
Avatar billede arne_v Ekspert
07. januar 2005 - 22:17 #2
Tiden på den remote fil er lidt sværere, men jeg har copy pastet lidt kode sammen.
Avatar billede arne_v Ekspert
07. januar 2005 - 22:18 #3
Imports System
Imports System.Globalization
Imports System.IO
Imports System.Text
Imports System.Net.Sockets
Imports System.Threading

Public Class FtpClient
    Private ctrl As TcpClient
    Private ctrlstm As NetworkStream
    Private data As TcpClient
    Private datastm As NetworkStream

    Private Shared Sub Send(ByVal stm As NetworkStream, ByVal line As String)
        Dim b As Byte() = Encoding.Default.GetBytes(line)
        stm.Write(b, 0, b.Length)
    End Sub

    Private Shared Function Receive(ByVal stm As NetworkStream) As String
        Dim b(100000 - 1) As Byte
        Dim ix As Integer = 0
        Dim n As Integer
        While stm.DataAvailable
            n = stm.Read(b, ix, b.Length - ix)
            ix += n
        End While
        Return Encoding.Default.GetString(b, 0, ix)
    End Function

    Public Shared Function Command(ByVal stm As NetworkStream, ByVal cmd As String) As String
        Send(stm, cmd + Convert.ToChar(13) + Convert.ToChar(10))
        Thread.Sleep(250)
        Return Receive(stm)
    End Function

    Private Sub SetupData()
        Dim dataaddr As String = Command(ctrlstm, "PASV")
        Dim addrparts As String() = dataaddr.Split("()".ToCharArray)(1).Split(",".ToCharArray)
        Dim datahost As String = addrparts(0) + "." + addrparts(1) + "." + addrparts(2) + "." + addrparts(3)
        Dim dataport As Integer = Integer.Parse(addrparts(4)) * 256 + Integer.Parse(addrparts(5))
        data = New TcpClient (datahost, dataport)
        datastm = data.GetStream
    End Sub

    Public Sub New(ByVal host As String, ByVal username As String, ByVal password As String)
        ctrl = New TcpClient (host, 21)
        ctrlstm = ctrl.GetStream
        Command(ctrlstm, "USER " + username)
        Command(ctrlstm, "PASS " + password)
    End Sub

    Public Function Dir() As String
        SetupData
        Command(ctrlstm, "LIST")
        Dim res As String = Receive(datastm)
        Receive(ctrlstm)
        datastm.Close
        data.Close
        Return res
    End Function

    Public Function ShortDir() As String
        SetupData
        Command(ctrlstm, "NLST")
        Dim res As String = Receive(datastm)
        Receive(ctrlstm)
        datastm.Close
        data.Close
        Return res
    End Function

    Public Sub MkDir(ByVal dir As String)
        Command(ctrlstm, "MKD " + dir)
    End Sub

    Public Sub RmDir(ByVal dir As String)
        Command(ctrlstm, "RMD " + dir)
    End Sub

    Public Sub ChDir(ByVal dir As String)
        Command(ctrlstm, "CWD " + dir)
    End Sub

    Public Sub UpLoad(ByVal filename As String, ByVal binary As Boolean)
        If binary Then
            Command(ctrlstm, "TYPE I")
        Else
            Command(ctrlstm, "TYPE A")
        End If
        SetupData
        Command(ctrlstm, "STOR " + filename)
        Receive(ctrlstm)
        Dim f As FileStream = New FileStream (filename, FileMode.Open)
        Dim b(100000 - 1) As Byte
        Dim ix As Integer = 0
        Dim n As Integer
        While ix < f.Length
            n = f.Read(b, 0, b.Length)
            datastm.Write(b, 0, n)
            Thread.Sleep(100)
            ix += n
        End While
        f.Close
        datastm.Close
        data.Close
    End Sub

    Public Sub DownLoad(ByVal filename As String, ByVal binary As Boolean)
        If binary Then
            Command(ctrlstm, "TYPE I")
        Else
            Command(ctrlstm, "TYPE A")
        End If
        SetupData
        Command(ctrlstm, "RETR " + filename)
        Receive(ctrlstm)
        Dim f As FileStream = New FileStream (filename, FileMode.Create)
        Dim b(100000 - 1) As Byte
        Dim n As Integer
        While datastm.DataAvailable
            n = datastm.Read(b, 0, b.Length)
            f.Write(b, 0, n)
            Thread.Sleep(100)
        End While
        f.Close
        datastm.Close
        data.Close
    End Sub

    Public Function Dir(ByVal filename As String) As String
        SetupData
        Command(ctrlstm, "LIST " + filename)
        Dim res As String = Receive(datastm)
        Receive(ctrlstm)
        datastm.Close
        data.Close
        Return res
    End Function

    Public Shared Function Eater(ByVal line As String, ByVal ix As Integer, ByVal n As Integer) As String
        Dim res As String = ""
        Dim line2() As Char = line.ToCharArray
        Dim ws As Integer = 0
        Dim i As Integer
        For i = 1 To (line2.Length - 1)
            If line2(i) = " " And line2(i-1) <> " " Then
                ws = ws + 1
            End If
            If ws >= ix And ws < (ix + n) Then
                res = res & line2(i)
            End If
        Next
        Eater = res.Trim
    End Function
   
    Public Shared Function ParseTime(ByVal line As String) As String
        ParseTime = Eater(line, 5, 3)
    End Function

    Public Function FileTime(ByVal filename As String) As DateTime
        Dim fmt() As String = { "MMM dd HH:mm", "MMM dd yyyy" }
        FileTime = DateTime.ParseExact(ParseTime(Dir(filename)), fmt, Nothing, DateTimeStyles.AllowWhiteSpaces)
    End Function

    Public Sub Logout()
        Command(ctrlstm, "QUIT")
        ctrlstm.Close
        ctrl.Close
    End Sub
End Class

Class TestClass
    Public Shared Sub Main(ByVal args As String())
        Dim cli As FtpClient = New FtpClient ("localhost", "anonymous", "arne@")
        Console.WriteLine(cli.FileTime("makefile"))
        Console.WriteLine(cli.FileTime("mouse.c"))
        cli.Logout
    End Sub
End Class
Avatar billede arne_v Ekspert
07. januar 2005 - 22:19 #4
Der er ikke nogen standard for formatet på DIR output fra FTP servere.

Jeg har testet mod min Linux server.

Hvis din server bruger andre formater, så tilføjer du dem bare til
fmt listen.
Avatar billede jens_k Nybegynder
07. januar 2005 - 22:24 #5
Der er lidt at gå igang med :-)

Jeg tjekker det med det samme.

Du hører fra mig senere iaften.

Mvh Jens_K
Avatar billede arne_v Ekspert
07. januar 2005 - 22:41 #6
Jeg er snart på vej i seng og vil nok ikke være på igen før i morgen aften ...
Avatar billede jens_k Nybegynder
13. januar 2005 - 11:50 #7
Hej Arne,

Jeg bøvler lidt med at jeg får denne fejl:

An exception 'System.FormatException' has occurred in FTP.exe

Ved du hvad det kan være ?

Mvh

Jens K
Avatar billede jens_k Nybegynder
13. januar 2005 - 11:52 #8
Doh, det er selvfølgelig dem jeg skal tilføje til fmt listen.

Hvordan kan jeg se hvilket format min FTP server kører med ?

Til at teste med bruger jeg Microsoft FTP (Den som ligger i IIS), men det skal køre på en BulletProff FTP Server bagefter..

Hvordan kan jeg tjekke det ?

Mvh

Jens K
Avatar billede arne_v Ekspert
13. januar 2005 - 11:57 #9
Du starter en command line FTP client, logger ind på FTP serveren, laver en
DIR og studerer formatet.
Avatar billede jens_k Nybegynder
13. januar 2005 - 12:33 #10
Okay, og så får jeg dette:

230 Anonymous user logged in.
ftp> dir
200 PORT command successful.
150 Opening ASCII mode data connection for /bin/ls.
01-13-05  11:47AM                    6 test1.txt
01-13-05  11:47AM                    6 test2.txt
226 Transfer complete.
ftp: 100 byte modtaget på 0.00 sekunder 100000.00 ved Kbyte/sek.
ftp>

Hvordan vil du så sætte det op? Jeg synes ikke helt jeg kan se det..

Mvh

Jens K
Avatar billede arne_v Ekspert
13. januar 2005 - 12:56 #11
Så skal der både tilføjet et tidsformat i fmt og hvad der er værre: du skal
også have rettet i argumenterne til eater.

Alternativt skal du rette i din IIS config så den viser listning i Unix format.

Det sidste er nok bedst da jeg gætter på at BulletProof FTP server bruger det
format.
Avatar billede jens_k Nybegynder
13. januar 2005 - 13:39 #12
Nu har jeg lige skiftet den over til BulletProof FTP Server, og nu ser formatet således ud, men det virker stadig ikke:

230 User jk logged in.
ftp> dir
200 Port command successful.
150 Opening data connection for directory list.
-rw-r--r--  1 ftp      ftp            6 Jan 13 11:47 test1.txt
-rw-r--r--  1 ftp      ftp            6 Jan 13 11:47 test2.txt
226 Transfer ok
ftp: 132 byte modtaget på 0.00 sekunder 132000.00 ved Kbyte/sek.
ftp>
Avatar billede jens_k Nybegynder
13. januar 2005 - 13:42 #13
Nu kommer der ikke nogen fejl længere..

Hvis jeg gerne vil have at vinduet bliver oppe indtil jeg trykker på en f.eks "enter", hvordan gør jeg så lige? Nu lukker mit console vindue jo med det samme..
Avatar billede jens_k Nybegynder
13. januar 2005 - 14:10 #14
Nu hvor jeg kan hente tiderne på dem begge, hvordan laver jeg så sådan at den kun uploader filerne hvis de er ændret siden sidst ?

Mvh

Jens K
Avatar billede arne_v Ekspert
13. januar 2005 - 14:53 #15
dt1 = cli.FileTime(filnavn)
dt2 = File.GetLastWriteTime(filnavn)
If dt1 > dt2 Then
...
End If
Avatar billede arne_v Ekspert
13. januar 2005 - 14:53 #16
omvendt

If dt1 < dt2 Then
Avatar billede jens_k Nybegynder
13. januar 2005 - 15:20 #17
Og når jeg skal lave variablen, hvilken datatype skal jeg så bruge?

Jeg har lavet det på følgende måde, men det virker ikke. Den returnere altid tiden 12:00:00" fra FTPen, og uden en dato.

Dim fName As String = Path.GetFileName(f)
Dim dt1 As String = cli.FileTime(fName)
Dim dt2 As String = File.GetLastWriteTime(f)

Nogen forslag ?

Mvh

Jens
Avatar billede arne_v Ekspert
13. januar 2005 - 15:23 #18
DateTime
Avatar billede jens_k Nybegynder
13. januar 2005 - 15:26 #19
Hvis jeg i min app. skriver:

Console.WriteLine(cli.FileTime("test1.txt"))

Så returnere den dette: 1/1/0001 12:00:00 AM

Det er heller ikke helt korrekt, den burde returnere: 1/13/2005 15:18

Så skal bruge lidt hjælp :-)

Mvh

Jens K
Avatar billede arne_v Ekspert
13. januar 2005 - 15:29 #20
Jeg tester dit 13:39:15 i aften og ser om det er fmt eller Eater argumenterne
der skal rettes til.
Avatar billede jens_k Nybegynder
13. januar 2005 - 15:31 #21
Det lyder bare super, jeg venter spændt :-)

Mvh

Jens K
Avatar billede jens_k Nybegynder
13. januar 2005 - 20:57 #22
Hva så Arne, nu har du vel ikke glemt mig ? :-)

Mvh

Jens K
Avatar billede arne_v Ekspert
13. januar 2005 - 21:06 #23
Næh.

Men jeg er lidt kørt fast.

Når jeg parser linien:

"-rw-r--r--  1 ftp      ftp            6 Jan 13 11:47 test1.txt"

så får jeg:

13-01-2005 11:47:00

hvilket ikke er korrekt men ikke det som du gør.
Avatar billede arne_v Ekspert
13. januar 2005 - 21:08 #24
vrøvl - det da korrekt - de 6 er størrelsen
Avatar billede jens_k Nybegynder
13. januar 2005 - 22:06 #25
Det vil sige at det virker eller ?
Avatar billede arne_v Ekspert
13. januar 2005 - 22:15 #26
Det er jo så meget sagt.

Jeg har bare svært ved at genslabe din fejl.
Avatar billede jens_k Nybegynder
13. januar 2005 - 22:24 #27
Okay, jeg prøver lige at rode lidt videre... Du får lige en melding om lidt.
Avatar billede arne_v Ekspert
22. januar 2005 - 22:39 #28
Virkede det ?

(og et svar)
Avatar billede arne_v Ekspert
30. januar 2005 - 19:56 #29
??
Avatar billede jens_k Nybegynder
08. april 2005 - 14:13 #30
Hej Arne,

Du må meget undskylde det sene svar.

Men ja, jeg tror vist jeg har fået det til at fungere.

Du må meget undskylde den sene respons.

Men her er din velfortjente points.

Tusinde tak for hjælpen

Mvh

Jens K
Avatar billede Ny bruger Nybegynder

Din løsning...

Tilladte BB-code-tags: [b]fed[/b] [i]kursiv[/i] [u]understreget[/u] Web- og emailadresser omdannes automatisk til links. Der sættes "nofollow" på alle links.

Loading billede Opret Preview
Kategori
Kurser inden for grundlæggende programmering

Log ind eller opret profil

Hov!

For at kunne deltage på Computerworld Eksperten skal du være logget ind.

Det er heldigvis nemt at oprette en bruger: Det tager to minutter og du kan vælge at bruge enten e-mail, Facebook eller Google som login.

Du kan også logge ind via nedenstående tjenester