21

Basically I have a url/link to a text file online and I am trying to download it locally. For some reason, the text file that gets created/downloaded is blank. Open to any suggestions. Thanks!

    def downloadFile(token: String, fileToDownload: String) {

    val url = new URL("http://randomwebsite.com/docs?t=" + token + "&p=tsr%2F" + fileToDownload)
    val connection = url.openConnection().asInstanceOf[HttpURLConnection]
    connection.setRequestMethod("GET")
    val in: InputStream = connection.getInputStream
    val fileToDownloadAs = new java.io.File("src/test/resources/testingUpload1.txt")
    val out: OutputStream = new BufferedOutputStream(new FileOutputStream(fileToDownloadAs))
    val byteArray = Stream.continually(in.read).takeWhile(-1 !=).map(_.toByte).toArray
    out.write(byteArray)
    }
slizorn
  • 315
  • 1
  • 4
  • 14

4 Answers4

40

I know this is an old question, but I just came across a really nice way of doing this :

import sys.process._
import java.net.URL
import java.io.File

def fileDownloader(url: String, filename: String) = {
    new URL(url) #> new File(filename) !!
}

Hope this helps. Source.

You can now simply use fileDownloader function to download the files.

fileDownloader("http://ir.dcs.gla.ac.uk/resources/linguistic_utils/stop_words", "stop-words-en.txt")
David P
  • 3,604
  • 3
  • 37
  • 54
Chetan Bhasin
  • 3,503
  • 1
  • 23
  • 36
11

Here is a naive implementation by scala.io.Source.fromURL and java.io.FileWriter

def downloadFile(token: String, fileToDownload: String) {
  try {
    val src = scala.io.Source.fromURL("http://randomwebsite.com/docs?t=" + token + "&p=tsr%2F" + fileToDownload)
    val out = new java.io.FileWriter("src/test/resources/testingUpload1.txt")
    out.write(src.mkString)
    out.close
  } catch {
    case e: java.io.IOException => "error occured"
  }
}

Your code works for me... There are other possibilities that make empty file.

Herrington Darkholme
  • 5,979
  • 1
  • 27
  • 43
10

Here is a safer alternative to new URL(url) #> new File(filename) !!:

val url = new URL(urlOfFileToDownload)

val connection = url.openConnection().asInstanceOf[HttpURLConnection]
connection.setConnectTimeout(5000)
connection.setReadTimeout(5000)
connection.connect()

if (connection.getResponseCode >= 400)
  println("error")
else
  url #> new File(fileName) !!

Two things:

  • When downloading from an URL object, if an error (404 for instance) is returned, then the URL object will throw a FileNotFoundException. And since this exception is generated from another thread (as URL happens to run on a separate thread), a simple Try or try/catch won't be able to catch the exception. Thus the preliminary check for the response code: if (connection.getResponseCode >= 400).
  • As a consequence of checking the response code, the connection might sometimes get stuck opened indefinitely for improper pages (as explained here). This can be avoided by setting a timeout on the connection: connection.setReadTimeout(5000).
Xavier Guihot
  • 54,987
  • 21
  • 291
  • 190
6

Flush the buffer and then close your output stream.

Eric Hydrick
  • 3,467
  • 2
  • 28
  • 41