Autor Beitrag
Kasko
ontopic starontopic starontopic starontopic starontopic starontopic starontopic starontopic star
Beiträge: 106

Win 10
C# C++ (VS 2017/19), (Java, PHP)
BeitragVerfasst: Sa 17.10.20 03:04 
Servus,

Ist es möglich die Endposition einer FTPWebRequest zu setzten oder die Anzahl der Bytes die ausgelesen werden sollen? Zusammen mit einer initialen Position könnte dies die Endposition ersetzten. Falls dies nicht möglich ist, könnte man den ResponseStream an einer bestimmten Stelle abschneiden? Innerhalb einer HttpWebRequest ist dies ja möglich mit der Methode AddRange, und dass obwohl http nicht immer partielle Anfragen unterstützt (kommt auf den Host an). FTP hingegen unterstützt immer partielle Anfragen und hier ist es nicht möglich. Hier ein bisschen Code um zu zeigen was ich machen möchte

Wichtig:
Ich möchte das Auslesen aus dem Stream nicht einfach nach einer gewissen Anzahl von bytes abbrechen. Dies ist mit der Architektur meiner Bibliothek nicht zu vereinbaren:
  1. Ein SourceExtractor (Name steht noch nicht fest) ließt für registrierte Hosts die tatsächlichen Urls zu den Dateien (1-n) aus. Zb.: www.youtube.com/watch?v=id --> youtube.com/path/to/file
  2. Die ProtocolProviderFactory erstellt einen für die ausgelesene Url einen Provider der das geforderte Protocol unterstützt. Dieser liest die Informationen der Resource aus und liefert einen Stream zurück.
  3. Der Download arbeitet, unabhängig von den verschiedenen Arten der Datentransferprotocolle, nur mit dem Stream und liest die entsprechenden Bytes aus. Er kümmert sich nicht um gesondertes Verhalten für bestimmte Arten von Protocollen, sonst wäre die Bibliothek deulich schlechter zu erweitern, vor allem für Nutzer die den Code des Downloads nicht ändern können.


Klasse:
ausblenden C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
namespace GDL.Protocols {
    public class FtpProtocolProvider : ProtocolProvider {
        /// <summary>
        /// Creates a stream to the resource, specified by its <see cref="ResourceIdentifier"/>.
        /// </summary>
        /// <param name="resourceIdentifier">The identifier of the resource.</param>
        /// <param name="initialPosition">The offset of the stream.</param>
        /// <param name="endPosition">The end position of the stream.</param>
        /// <returns>The created stream.</returns>
        public override Stream CreateStream(ResourceIdentifier resourceIdentifier, long initialPosition, long endPosition) {
            FtpWebRequest request = CreateRequest(resourceIdentifier) as FtpWebRequest;

            request.Method = WebRequestMethods.Ftp.DownloadFile;
        
            if (initialPosition > 0)
                request.ContentOffset = initialPosition;

            return request.GetResponse().GetResponseStream();
        }
    }
}


Die für diese Frage relevanten Tests:
ausblenden volle Höhe C#-Quelltext
1:
2:
3:
4:
5:
6:
7:
8:
9:
10:
11:
12:
13:
14:
15:
16:
17:
18:
19:
20:
21:
22:
23:
24:
25:
26:
27:
28:
29:
30:
31:
32:
33:
34:
35:
36:
37:
38:
39:
40:
namespace GDL.IntegrationTests {
    [TestClass]
    public class FtpProtocolProviderTests {
        [TestMethod]
        public void CreateStream_FtpTestTxt_ReturnsValidStream() {
            string url = "ftp://test-domain.com/public/provider-test/test.txt";
            ResourceIdentifier resourceIdentifier = new ResourceIdentifier(new Uri(url), new FtpTestNetworkCredential());

            ProtocolProvider provider = ProtocolProviderFactory.CreateProvider(url);
            Stream stream = provider.CreateStream(resourceIdentifier, 00);

            StreamReader reader = new StreamReader(stream);
            Assert.IsTrue(reader.ReadToEnd().Equals("If this text was read out, the stream works!"));
        }

        [TestMethod]
        public void CreateStream_FtpTestTxtInitialPositionSet_ReturnsValidStream() {
            string url = "ftp://test-domain.com/public/provider-test/test.txt";
            ResourceIdentifier resourceIdentifier = new ResourceIdentifier(new Uri(url), new FtpTestNetworkCredential());

            ProtocolProvider provider = ProtocolProviderFactory.CreateProvider(url);
            Stream stream = provider.CreateStream(resourceIdentifier, 30);

            StreamReader reader = new StreamReader(stream);
            Assert.IsTrue(reader.ReadToEnd().Equals("this text was read out, the stream works!"));
        }

        [TestMethod]
        public void CreateStream_FtpTestTxtEndPositionSet_ReturnsValidStream() {
            string url = "ftp://test-domain.com/public/provider-test/test.txt";
            ResourceIdentifier resourceIdentifier = new ResourceIdentifier(new Uri(url), new FtpTestNetworkCredential());

            ProtocolProvider provider = ProtocolProviderFactory.CreateProvider(url);
            Stream stream = provider.CreateStream(resourceIdentifier, 037);

            StreamReader reader = new StreamReader(stream);
            Assert.IsTrue(reader.ReadToEnd().Equals("If this text was read out, the stream"));  //<---- this should be possible.
        }
    }
}


Geht vor allem um Zeile 34-37.

Danke im Voraus :)


Moderiert von user profile iconTh69: Topic aus C# - Die Sprache verschoben am Sa 17.10.2020 um 10:39
Moderiert von user profile iconTh69: Titel geändert ("C#" entfernt).