【问题标题】:Download file without knowing its size在不知道文件大小的情况下下载文件
【发布时间】:2014-03-18 19:49:05
【问题描述】:

我正在使用 URLConnection、DataInputStream 和 FileOutputStream 下载文件。我正在使用在线文件的大小(使用 getContentLength())创建一个巨大的字节 []。问题是,当我尝试下载大文件时,出现 OutOfMemoryError: Java heap space,这是正常行为。

代码如下:

    URLConnection con;
    DataInputStream dis;  
    FileOutputStream fos;
    byte[] fileData = null;

    URL url = new URL(from);
    con = url.openConnection();                  

    con.setUseCaches(false);
    con.setDefaultUseCaches(false);
    con.setRequestProperty("Cache-Control", "no-store,max-age=0,no-cache");
    con.setRequestProperty("Expires", "0");
    con.setRequestProperty("Pragma", "no-cache");
    con.setConnectTimeout(5000);
    con.setReadTimeout(30000);

    dis = new DataInputStream(con.getInputStream());

    int contentLength = con.getContentLength();

    //Taille connue
    if (contentLength != -1)
    {
        fileData = new byte[con.getContentLength()];

        for (int x = 0; x < fileData.length; x++) 
        {             
            fileData[x] = dis.readByte();

            if (listener != null)
            {
                listener.onFileProgressChanged(x, fileData.length);
            }
        }
    }
    //Taille inconnue
    else
    {
        System.out.println("Attention : taille du fichier inconnue !");
        if (undefinedListener != null)
        {
            undefinedListener.onUndefinedFile();
        }
        ByteArrayOutputStream stream = new ByteArrayOutputStream();
        while (true)
        {
            try
            {
                stream.write(dis.readByte());
            }
            catch (EOFException ex)
            {
                //Fin
                fileData = stream.toByteArray();
                stream.close();             
            }
        }
    }

    dis.close(); 

    //Ecriture
    fos = new FileOutputStream(file);
    fos.write(fileData);  
    fos.close();    

我听说我应该将文件分成块以避免它。我知道该怎么做,这很容易,但是......如果文件的 ContentLength 不能从服务器显示为红色 (getContentLength() == -1) 我该怎么做?如果我不知道文件的大小,我应该如何将文件分成块?

谢谢!

【问题讨论】:

  • 你为什么使用DataInputStream
  • 显示您现在使用的代码。几乎可以肯定有一个简单的解决方案,它可能涉及 Apache Commons IOUtils

标签: java file memory download


【解决方案1】:

我正在用在线文件的大小创建一个巨大的字节[]

为什么?您不需要文件大小的字节数组。这只会浪费空间并增加延迟。只需读写缓冲区:

while ((count = in.read(buffer)) > 0)
{
    out.write(buffer, 0, count);
}

这适用于任何大小大于零的 byte[] 缓冲区。我一般用8192。

使用 URLConnection 您也不需要内容长度:只需像上面那样读取 EOS。

【讨论】:

  • 我这样做了,它有效,谢谢 :) 问题是当你中断下载时(例如通过关闭窗口)你还有一个下载一半的文件 =/ 我怎样才能删除如果下载尚未完全完成,该文件?
【解决方案2】:

根本没有理由使用DataInputStream。使用Files:

final Path dstFile = Paths.get("path/to/dstfile");
Files.copy(url.openStream(), dstFile);

【讨论】:

    猜你喜欢
    • 1970-01-01
    • 2017-04-26
    • 2016-12-29
    • 2014-08-10
    • 2023-03-20
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    • 2010-10-05
    相关资源
    最近更新 更多