安卓Java - 如何从URL下载zip文件?

4
嘿,我正在制作一个新项目,需要你从我的Dropbox下载一些文件。我添加了一个名为DownloadFile的新类,其中包含下载文件的代码。出现问题的是,当我点击下载时,应用程序会崩溃。谢谢。
这是DownloadFile:
    package com.Matt7262.download.app;

    import android.support.v7.app.ActionBarActivity;
    import android.os.Bundle;
    import android.view.Menu;
    import android.view.MenuItem;
    //Chat bot library
    import org.alicebot.ab.Chat;
    import org.alicebot.ab.Bot;

    import android.view.View;
    import android.widget.Button;
    import android.os.Environment;
    import android.widget.TextView;
    import android.widget.Toast;

    import java.io.InputStream;
    import java.net.URL;
    import java.io.DataInputStream;
    import java.io.DataOutputStream;
    import java.io.File;
    import java.io.FileNotFoundException;
    import java.io.FileOutputStream;
    import java.io.IOException;
    import java.net.HttpURLConnection;
    import java.net.MalformedURLException;
    import android.widget.ProgressBar;
    import java.net.URL;
    import java.net.URLConnection;
    import android.app.Activity;
    import android.app.ProgressDialog;
    import android.os.Environment;
    import android.view.View.OnClickListener;

    public class DownloadFile extends ActionBarActivity{

    public void updateProgress(int currentSize, int totalSize)
    {
        Toast.makeText(getApplicationContext(), "Loading Files...",
                Toast.LENGTH_SHORT).show();
    }

    public void Download()
    {
        try {
            //set the download URL, a url that points to a file on the internet
            //this is the file to be downloaded
            URL url = new URL("https://dl.dropboxusercontent.com/shz/9cyfz0b45mj6szr/7pBuupNz3N/xecta?token_hash=AAEs9cDFswt98D1IhLnab4dHwhwh5z2Lmhq_N6H-2M0LWg&top_level_offset=6");

            //create the new connection
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

            //set up some things on the connection
            urlConnection.setRequestMethod("GET");
            urlConnection.setDoOutput(true);

            //and connect!
            urlConnection.connect();

            //set the path where we want to save the file
            //in this case, going to save it on the root directory of the
            //sd card.
            File SDCardRoot = Environment.getExternalStorageDirectory();
            //create a new file, specifying the path, and the filename
            //which we want to save the file as.
            File file = new File(SDCardRoot,"hello.zip");

            //this will be used to write the downloaded data into the file we created
            FileOutputStream fileOutput = new FileOutputStream(file);

            //this will be used in reading the data from the internet
            InputStream inputStream = urlConnection.getInputStream();

            //this is the total size of the file
            int totalSize = urlConnection.getContentLength();
            //variable to store total downloaded bytes
            int downloadedSize = 0;

            //create a buffer...
            byte[] buffer = new byte[1024];
            int bufferLength = 0; //used to store a temporary size of the buffer

            //now, read through the input buffer and write the contents to the file
            while ( (bufferLength = inputStream.read(buffer)) > 0 ) {
                //add the data in the buffer to the file in the file output stream (the file on the sd card
                fileOutput.write(buffer, 0, bufferLength);
                //add up the size so we know how much is downloaded
                downloadedSize += bufferLength;
                //this is where you would do something to report the prgress, like this maybe
                updateProgress(downloadedSize, totalSize);

            }
            //close the output stream when done
            fileOutput.close();

            //catch some possible errors...
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }
    }

主活动:

package com.Matt7262.download.app;

import android.support.v7.app.ActionBarActivity;
import android.os.Bundle;
import android.view.Menu;
import android.view.MenuItem;
//Chat bot library
import org.alicebot.ab.Chat;
import org.alicebot.ab.Bot;

import android.view.View;
import android.widget.Button;
import android.os.Environment;
import android.widget.TextView;
import android.widget.Toast;

import android.os.AsyncTask;

public class MainActivity extends ActionBarActivity {

    TextView input;
    String dPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Download";
    private DownloadFile df;

    @Override
    protected void onCreate(Bundle savedInstanceState) {
        super.onCreate(savedInstanceState);
        setContentView(R.layout.activity_main);
    }

    //EditText mEdit = (EditText)findViewById(R.id.editText1);

    public void buttonOnClick(View v)
    {
        input = (TextView) findViewById(R.id.editText1);

        String dbPath = Environment.getExternalStorageDirectory().getAbsolutePath() + "/Download/Ab";

        Button button=(Button) v;

        //Creating bot
        String botname="xecta";
        String path= dbPath;
        Bot xecta = new Bot(botname, path);

        Chat chatSession = new Chat(xecta);

        String request = input.getText().toString();
        String response = chatSession.multisentenceRespond(request);
        ((Button) v).setText(response);
    }

    public void onClickDownload(View view)
    {
        df.Download();
    }

    @Override
    public boolean onCreateOptionsMenu(Menu menu) {

        // Inflate the menu; this adds items to the action bar if it is present.
        getMenuInflater().inflate(R.menu.main, menu);
        return true;
    }

    @Override
    public boolean onOptionsItemSelected(MenuItem item) {
        // Handle action bar item clicks here. The action bar will
        // automatically handle clicks on the Home/Up button, so long
        // as you specify a parent activity in AndroidManifest.xml.
        int id = item.getItemId();
        if (id == R.id.action_settings) {
            return true;
        }
        return super.onOptionsItemSelected(item);
    }

    /*public void updateProgress(int currentSize, int totalSize)
    {
        Toast.makeText(getApplicationContext(), "Retrieving Files...",
                Toast.LENGTH_SHORT).show();
    }/*

    /*public void Download()
    {
        try {
            //set the download URL, a url that points to a file on the internet
            //this is the file to be downloaded
            URL url = new URL("https://dl.dropboxusercontent.com/shz/9cyfz0b45mj6szr/7pBuupNz3N/xecta?token_hash=AAEs9cDFswt98D1IhLnab4dHwhwh5z2Lmhq_N6H-2M0LWg&top_level_offset=6");

            //create the new connection
            HttpURLConnection urlConnection = (HttpURLConnection) url.openConnection();

            //set up some things on the connection
            urlConnection.setRequestMethod("GET");
            urlConnection.setDoOutput(true);

            //and connect!
            urlConnection.connect();

            //set the path where we want to save the file
            //in this case, going to save it on the root directory of the
            //sd card.
            File SDCardRoot = Environment.getExternalStorageDirectory();
            //create a new file, specifying the path, and the filename
            //which we want to save the file as.
            File file = new File(SDCardRoot,"hello.zip");

            //this will be used to write the downloaded data into the file we created
            FileOutputStream fileOutput = new FileOutputStream(file);

            //this will be used in reading the data from the internet
            InputStream inputStream = urlConnection.getInputStream();

            //this is the total size of the file
            int totalSize = urlConnection.getContentLength();
            //variable to store total downloaded bytes
            int downloadedSize = 0;

            //create a buffer...
            byte[] buffer = new byte[1024];
            int bufferLength = 0; //used to store a temporary size of the buffer

            //now, read through the input buffer and write the contents to the file
            while ( (bufferLength = inputStream.read(buffer)) > 0 ) {
                //add the data in the buffer to the file in the file output stream (the file on the sd card
                fileOutput.write(buffer, 0, bufferLength);
                //add up the size so we know how much is downloaded
                downloadedSize += bufferLength;
                //this is where you would do something to report the prgress, like this maybe
                updateProgress(downloadedSize, totalSize);

            }
            //close the output stream when done
            fileOutput.close();

         //catch some possible errors...
        } catch (MalformedURLException e) {
            e.printStackTrace();
        } catch (IOException e) {
            e.printStackTrace();
        }
    }*/


}

我想这是我从logcat中得到的所有信息:

logcat


1
应用程序可能会崩溃,因为您正在尝试在UI线程上下载。尝试启动一个新的异步任务来为您下载文件 :) - Pphoenix
我该怎么做,@Pphoenix?谢谢 :) - 71m3
@Pphoenix,当需要与UI进行交互(更新)时,可以使用asynctask! - user1650415
@SELMANON 哦,是的,我只是假设他使用了 UI 更新 :) - Pphoenix
2个回答

4

你声明了 DownloadFile 对象,但没有初始化它。

private DownloadFile df;
df.Download(); // Throws NPE

不要忘记对其进行初始化。
private DownloadFile df = new DownloadFile();
df.Download();

编辑:

现在您已经初始化了对象并避免了NPE,但这一次您遇到了NetworkOnMainThreadException。在Honeycomb版本之后,Android不允许您在主线程上进行网络操作。您可以使用AsyncTask来解决这个问题。


谢谢@Tim,但我把私有的DownloadFile df;放在“public class MainActivity extends ActionBarActivity”下面,并且放置了df = new DownloadFile(); df.Download(); 但它仍然无法工作。 - 71m3
通过初始化,您解决了NPE问题。现在可能是另一个问题。查看logcat。 - Timuçin
我会在帖子中添加新的logcat。@Tim - 71m3
我添加了新的logcat @Tim。 - 71m3
感谢 @Tim,这很有帮助。 - 71m3

0
在Kotlin中,这个函数非常有用,使用try/catch可以避免崩溃并向用户发送Toast消息。
之后可能需要解压缩文件,请查看此链接https://dev59.com/gnA75IYBdhLWcg3wRW2c#76032406
fun downloadZip() {


        val url = URL("http://www.Any.com/sub/name.zip")

        Thread {
            try {
                val con: HttpURLConnection = url.openConnection() as HttpURLConnection
                con.doInput = true
                con.connectTimeout = 1200
                con.connect()
                val responseCode = con.responseCode
               

                if (responseCode == HttpURLConnection.HTTP_OK) {
                    val m = con.inputStream
                    val inStream = BufferedInputStream(m, 1024 * 5)
                    val myFilename = "newFile"
                    val myExtensionVar = ".zip"
                    val file = File(
                        context.getDir("Music", AppCompatActivity.MODE_PRIVATE),
                        "/$myFilename$myExtensionVar"
                    )
                    
                    Log.i("well", "Downloaded file: $file")
                    if (file.exists()) {
                       file.delete()
                       
                    }else{
                    val buff = ByteArray(5 * 1024)
                    // Create File (Copy)
                    file.createNewFile()
                    val outStream = FileOutputStream(file)
                    var len:Int
                    while (inStream.read(buff).also { len = it } >= 0) {

                        outStream.write(buff, 0, len)


                    }

                    outStream.flush()
                    outStream.close()
                    inStream.close()
                    Log.i("well", "Done file: $file")

                    handler.post {
                        Toast.makeText(
                            context,
                            context.getString(R.string.mes_end_file), Toast.LENGTH_SHORT
                        ).show()
                      

                      
                    }
                    }
                }
            } catch (ex: Exception) {
                ex.printStackTrace()
                handler.sendMessage(handler.obtainMessage(22, "OK"))
            } catch (ex: IllegalThreadStateException){
                println( ex.printStackTrace())
                handler.sendMessage(handler.obtainMessage(22, "OK"))
            }

        }.start()

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接