[
https://issues.apache.org/jira/browse/NET-686?page=com.atlassian.jira.plugin.system.issuetabpanels:comment-tabpanel&focusedCommentId=17244465#comment-17244465
]
Vitaliy Khudenko edited comment on NET-686 at 12/5/20, 11:30 AM:
-----------------------------------------------------------------
Looks like I've encountered this issue too.
My setup is an Android app as an FTPS client running on a physical device
(Google Nexus, Android 8.1) or an emulator (Android 10) from Android Studio
(Win 10). VPN.
On the FTPS server I have 3 zip files (1, 4 and 74 KBytes).
Small files (1 and 4 KB) are never causing troubles. However for the largest
one the issue happens with ~25-33% probability.
The exact file size is 75'743 bytes. But it happens that only 75'741 bytes or
75'740 bytes is downloaded (missing just a few bytes) with no errors reported
by {{FTPSClient}}.
Here is my code (Kotlin):
{code:java}
private val CONNECT_TIMEOUT_MILLIS = 120_000 // 2 minutes
private val SO_TIMEOUT_MILLIS = 120_000 // 2 minutes
private val BUFFER_SIZE = 1024 // 1 KB
val client: FTPSClient = FTPSClient("TLS", false)
client.connectTimeout = CONNECT_TIMEOUT_MILLIS
client.connect(hostname, port)
client.soTimeout = SO_TIMEOUT_MILLIS
if (!FTPReply.isPositiveCompletion(client.replyCode)) {
throw Exception("FTP server refused connection")
}
if (!client.login(username, password)) {
throw Exception("FTP server refused to authenticate $username")
}
FileOutputStream(localTargetFile).use { outputStream: FileOutputStream ->
val status = client.retrieveFile(ftpFilePath, outputStream)
outputStream.flush()
check(status) { "negative retrieveFile status" } // throws Exception if
status is false, but this is always true
}
{code}
I tried to mitigate this with a retry mechanism where I would resume
downloading for the number of the missing bytes only (e.g. the second attempt
only fetches the last missing few bytes). But it still results in a corrupted
zip file, despite the total number of bytes is correct. Looks like the first
pass/attempt already brings a corrupted chunk, so resumed download does not
help:
{code:java}
repeat(ATTEMPTS_TO_DOWNLOAD) {
if (localTargetFile.exists()) {
client.restartOffset = localTargetFile.length()
FileOutputStream(localTargetFile, true)
} else {
FileOutputStream(localTargetFile)
}.use { outputStream: FileOutputStream ->
val status = client.retrieveFile(ftpFilePath, outputStream)
outputStream.flush()
check(status) { "negative retrieveFile status" } // throws Exception if
status is false, but this is always true
}
}{code}
The odd things I noticed (which is maybe due to FTPS server misconfig/missetup,
but FTPS server setup is beyond my control):
* {{FTPClient.mlistFile()}} always returns {{null}}
* I am not able to browse the FTPS content via WinSCP
was (Author: vkhudenko):
Looks like I've encountered this issue too.
My setup is an Android app as an FTPS client running on a physical device
(Google Nexus, Android 8.1) or an emulator (Android 10) from Android Studio
(Win 10). VPN.
On the FTPS server I have 3 zip files (1, 4 and 74 KBytes).
Small files (1 and 4 KB) are never causing troubles. However for the largest
one the issue happens with ~25-33% probability.
The exact file size is 75'743 bytes. But it happens that only 75'741 bytes or
75'740 bytes is downloaded (missing just a few bytes) with no errors reported
by {{FTPSClient}}.
Here is my code (Kotlin):
{code:java}
private val CONNECT_TIMEOUT_MILLIS = 120_000 // 2 minutes
private val SO_TIMEOUT_MILLIS = 120_000 // 2 minutes
private val BUFFER_SIZE = 1024 // 1 KB
val client: FTPSClient = FTPSClient("TLS", false)
client.connectTimeout = CONNECT_TIMEOUT_MILLIS
client.connect(config.hostname, config.port)
client.soTimeout = SO_TIMEOUT_MILLIS
if (!FTPReply.isPositiveCompletion(client.replyCode)) {
throw Exception("FTP server refused connection")
}
if (!client.login(username, password)) {
throw Exception("FTP server refused to authenticate $username")
}
FileOutputStream(localTargetFile).use { outputStream: FileOutputStream ->
val status = client.retrieveFile(ftpFilePath, outputStream)
outputStream.flush()
check(status) { "negative retrieveFile status" } // throws Exception if
status is false, but this is always true
}
{code}
I tried to mitigate this with a retry mechanism where I would resume
downloading for the number of the missing bytes only (e.g. the second attempt
only fetches the last missing few bytes). But it still results in a corrupted
zip file, despite the total number of bytes is correct. Looks like the first
pass/attempt already brings a corrupted chunk, so resumed download does not
help:
{code:java}
repeat(ATTEMPTS_TO_DOWNLOAD) {
if (localTargetFile.exists()) {
client.restartOffset = localTargetFile.length()
FileOutputStream(localTargetFile, true)
} else {
FileOutputStream(localTargetFile)
}.use { outputStream: FileOutputStream ->
val status = client.retrieveFile(ftpFilePath, outputStream)
outputStream.flush()
check(status) { "negative retrieveFile status" } // throws Exception if
status is false, but this is always true
}
}{code}
The odd things I noticed (which is maybe due to FTPS server misconfig/missetup,
but FTPS server setup is beyond my control):
* {{FTPClient.mlistFile()}} always returns {{null}}
* I am not able to browse the FTPS content via WinSCP
> Most files aren't downloaded completely from an FTP server
> ----------------------------------------------------------
>
> Key: NET-686
> URL: https://issues.apache.org/jira/browse/NET-686
> Project: Commons Net
> Issue Type: Bug
> Components: FTP
> Affects Versions: 3.6, 3.7.2
> Environment: Win 10
> Java 8
> Android Studio 3.6.1 (min SDK 24, target SDK 27)
> Reporter: JRRR
> Priority: Major
> Attachments: 2a-original.png, 2b-corrupt.png, 2c-corrupt.png,
> 5a-original.jpg, 5b-corrupt.jpg, 5c-corrupt.jpg, DownloadProblem.java
>
>
> About a month ago I opened another
> [issue|https://issues.apache.org/jira/browse/NET-684] that was closed because
> it wasn't reproducible with macOS and a public FTP server.
> Short summary: Downloading files from an FTP server results in these files
> randomly missing bytes. It looks like the download always "completes" and
> there are no error messages/exceptions but random bytes in random files are
> simply skipped. Images (jpg & png) are usually affected more (up to 30, maybe
> 40, bytes smaller than the original), and are then also visibly corrupt, than
> text files (usually only 2-3 bytes smaller, rarely more).
> I'm working on an Android app (Win 10, Java 8, Android Studio 3.6.1, min SDK
> 24, target SDK 27), which I'm testing with FTP servers in the same network
> (1x Win 10, 1x Linux, both accessed via IP - "10.1.1.xxx"). No matter what
> method in the library I use (retrieveFile, retrieveFileStream,
> sendCommand(FTPCmd.RETRIEVE, filename)), most of the time there's at least a
> single file that's corrupted.
> I also tested the same code with public servers and even though I didn't have
> a lot of time because those servers regularely delete uploaded files, I never
> experienced said problem with them.
> I even wrote my own mini-library (just for login/logout and download) using
> Java's default "Socket" but I still had the same problem on Android Studio's
> simulator/a real device. BUT: When I used the same code to create a small
> Windows/Swing/Java app, there were no more corrupted files.
> It looks like this bug is only affecting a very specific combination of
> OS,...:
> Android (emulator/real device) + Java (8) + FTP server in the same network
> (accessed via IP)
--
This message was sent by Atlassian Jira
(v8.3.4#803005)