Chris, thank's for input, I have solved this.
The problem was in this line:
in.available returns correct value, but in.read in some cases does not read the whole strem at a time, but only part of it (and returns number of read bytes).
so I have replaced these two line with a bigger section which always reads all bytes from input stream:
val buffer = new java.io.ByteArrayOutputStream()
val data = new Array[Byte](16384)
var nRead = in.read(data, 0, data.length)
while (nRead != -1) {
buffer.write(data, 0, nRead)
nRead = in.read(data, 0, data.length)
}
buffer.flush()
val bytes = buffer.toByteArray();
and in this way all works now.
For the reason why this could happen. On the local machine I run application from netbeans, and as I have found out, it does not run it from jar, but from output directory on filesystem - for example, this:
println(getClass.getResource("/public"))
on local machine (with netbeans) will print:
> file:/C:/xxx/snippets/scala-web/ScalaUnfilteredBasicDemo/target/classes/public
and on the remote machine I run application with java -jar and same call will print:
> jar:file:/home/ubuntu/scala/scala-unfiltered-basic-demo-1.0-SNAPSHOT.jar!/public
So, as I can see, when in.read(bytes) is called for local file, it will try to read the whole file at once (at least in my case with bigger image), and when called for resource file inside jar, it will read it in multiple steps (I have downloaded corrupted image from initial setup with curl and it gave me file with correct size, but it was filled with zeros at the end).
I also run Oracle JDK on local machine and OpenJDK on remote machine, which also might affect this in some way.
---
Anyway, by following your advice, I have added 'public' dir in resource to jetty startup line in this way:
unfiltered.jetty.Http.apply(8080).resources(getClass.getResource("/public")).plan(handlePath).run()
and now all images from '/public' are loaded automatically without any of the above code. The only trap here may be - the last section with any path handler should be removed from custom filter:
// case Path(Decode.utf8(Seg(path :: Nil))) =>
// Ok ~> PlainTextContent ~> ResponseString("Your segment: " + path)
because it will capture all requests and resources will never be loaded.
This also works for resources inside jar file and I really love this because in this way creating and running web application as normal jar file with all resources inside is much simpler, than deploying war file to tomcat (no need to install and confugure tomcat). For high loaded installations with many static content I would use nginx frontend with virtual filesystem directory for images and other static content.