Как да изтеглите големи файлове (размер › 50 MB) в java

Изтеглям файлове от отдалечено местоположение и изтеглянето е завършено за файлове с по-малък размер и незавършено за файлове с голям размер (>10 MB). Ето моя код, който използвах за изтегляне на файлове от отдалечен сървър.

    File dstFile = null;
    // check the directory for existence.
    String dstFolder = LOCAL_FILE.substring(0,LOCAL_FILE.lastIndexOf(File.separator));
    if(!(dstFolder.endsWith(File.separator) || dstFolder.endsWith("/")))
        dstFolder += File.separator;

    // Creates the destination folder if doesn't not exists
    dstFile = new File(dstFolder);
    if (!dstFile.exists()) {
        dstFile.mkdirs();
    }
    try {
        URL url = new URL(URL_LOCATION);
        HttpURLConnection connection = (HttpURLConnection) url.openConnection(); 
        connection.addRequestProperty("User-Agent", "Mozilla/4.76"); 
        //URLConnection connection = url.openConnection();
        BufferedInputStream stream = new BufferedInputStream(connection.getInputStream());
        int available = stream.available();
        byte b[]= new byte[available];
        stream.read(b);
        File file = new File(LOCAL_FILE);
        OutputStream out  = new FileOutputStream(file);
        out.write(b);
    } catch (Exception e) {
        System.err.println(e);
        VeBLogger.getInstance().log( e.getMessage());
    }

person Raguram    schedule 30.07.2014    source източник
comment
Съществува ли друг API за изтегляне на огромни файлове?   -  person Raguram    schedule 30.07.2014
comment
Какъв е всъщност вашият въпрос или какво не работи с този код?   -  person tier1    schedule 30.07.2014
comment
Обадете се на flush() на вашия FileOutputStream и след това close() на него.   -  person GriffeyDog    schedule 30.07.2014


Отговори (3)


Можете да използвате обща IO библиотека на apache. Това е лесно. Използвал съм го в много проекти.

File dstFile = null;
// check the directory for existence.
String dstFolder = LOCAL_FILE.substring(0,LOCAL_FILE.lastIndexOf(File.separator));
if(!(dstFolder.endsWith(File.separator) || dstFolder.endsWith("/")))
    dstFolder += File.separator;

// Creates the destination folder if doesn't not exists
dstFile = new File(dstFolder);
if (!dstFile.exists()) {
    dstFile.mkdirs();
}
try {
    URL url = new URL(URL_LOCATION);
    FileUtils.copyURLToFile(url, dstFile);
} catch (Exception e) {
    System.err.println(e);
    VeBLogger.getInstance().log( e.getMessage());
}
person bitkot    schedule 30.07.2014
comment
Амит : Благодаря за отговора ви. Има някакви ограничения по отношение на размера на файла, докато използвате FileUtils.copyURLToFile(url, dstFile), можем ли да изтеглим всички файлове (независимо от техния размер)? - person Raguram; 31.07.2014
comment
трябва ли да се погрижим за затварянето на потока, когато извикваме метода FileUtils.copyURLToFile(url, dstFile)? - person Raguram; 31.07.2014
comment
Няма нужда, вижте изходен код и няма ограничение в размера - person bitkot; 31.07.2014
comment
HiberKnight: Здравейте, дали този copyURLToFile() копира списъка с файлове, налични в директория от сървъра? имам предвид, че ако директория в сървъра има списък с файлове и ако предоставя местоположението на директорията като URL аргумент. тогава дали държи добре? - person Raguram; 13.08.2014
comment
Мисля, че не е възможно да изтеглите всички файлове от сървъра. Има ли API, който прави това? - person Raguram; 13.08.2014
comment
Не, не е. За целта трябва да изтеглите страницата на директорията, като посочите всички anchor тагове, да получите URL адреса за отделните файлове и след това да ги изтеглите в цикъл. - person bitkot; 13.08.2014
comment
Благодаря, но това изглежда е по-скъпа операция (получаване на HTML файла и анализиране на всички тагове). Съществува ли друг начин (или API с отворен код) за постигане на това? - person Raguram; 13.08.2014
comment
защото навсякъде в блоговете се говори само за изтегляне на файлове, а не за изтегляне на директория. - person Raguram; 13.08.2014
comment
HiberKnight: Как да получите URL адреса за отделни файлове в директория? - person Raguram; 13.08.2014

Първо бих ви препоръчал да използвате:

FileInputStream in = new FileInputStream(file);  

вместо:

BufferedInputStream in = new BufferedInputStream(new FileInputStream(file));

(За да избегнете натрупване на използване на паметта)

try
{
    FileInputStream fileInputStream  = new FileInputStream(file);
    byte[] buf=new byte[8192];
    int bytesread = 0, bytesBuffered = 0;
    while( (bytesread = fileInputStream.read( buf )) > -1 ) {
        out.write( buf, 0, bytesread );
        bytesBuffered += bytesread;
        if (bytesBuffered > 1024 * 1024) { //flush after 1MB
            bytesBuffered = 0;
            out.flush();
        }
    }
}
finally {
    if (out != null) {
        out.flush();
    }
}
person Rakesh Sharma    schedule 30.07.2014
comment
Изглежда странно да избягвате BufferedInputStream, когато прилагате точно буфер тук. Можете ли да обясните защо BufferedInputStream не е подходящ? - person ormurin; 12.01.2021

Моля, прочетете метода .available() на BufferedInputStream в API.

Той връща броя на наличните вече изтеглени байтове (т.е. броя на байтовете, които можете да прочетете от потока, без достъп/изчакване на мрежата).

Трябва да създадете байтов масив с фиксиран размер, fx. 2048 байта и използвайте методите read(), докато върне -1.

person Xabster    schedule 30.07.2014