2009-02-23 28 views
68

Tôi đang gặp sự cố khi tải xuống tệp nhị phân (video) trong ứng dụng của mình từ internet. Trong Quicktime, nếu tôi tải nó trực tiếp, nó hoạt động tốt nhưng thông qua ứng dụng của tôi bằng cách nào đó nó nhận được messed up (mặc dù họ trông giống hệt nhau trong một trình soạn thảo văn bản). Dưới đây là ví dụ:Tải xuống các vấn đề về tệp nhị phân của Android

URL u = new URL("http://www.path.to/a.mp4?video"); 
    HttpURLConnection c = (HttpURLConnection) u.openConnection(); 
    c.setRequestMethod("GET"); 
    c.setDoOutput(true); 
    c.connect(); 
    FileOutputStream f = new FileOutputStream(new File(root,"Video.mp4")); 


    InputStream in = c.getInputStream(); 

    byte[] buffer = new byte[1024]; 
    int len1 = 0; 
    while ((len1 = in.read(buffer)) > 0) { 
     f.write(buffer); 
    } 
    f.close(); 

Trả lời

91

Tôi không biết nếu đó là vấn đề duy nhất, nhưng bạn đã có một trục trặc Java cổ điển trong đó: Bạn sẽ không đếm trên thực tế là read() là luôn phép trả lại ít byte hơn bạn yêu cầu. Vì vậy, đọc của bạn có thể nhận được ít hơn 1024 byte nhưng viết của bạn luôn viết ra chính xác 1024 byte có thể bao gồm các byte từ lặp vòng lặp trước đó.

đúng với:

while ((len1 = in.read(buffer)) > 0) { 
     f.write(buffer,0, len1); 
} 

Có lẽ mạng độ trễ cao hơn hoặc kích thước gói nhỏ hơn của 3G trên Android đang làm trầm trọng thêm tác dụng?

+4

Thật là một sai lầm ngu ngốc ... cảm ơn! Đây là những gì sẽ xảy ra khi bạn không đọc hướng dẫn đúng :) –

+3

Cảm ơn ... đã giúp tôi. –

+0

Điều gì về việc khởi tạo bộ đệm? Điều gì về bảo vệ chống lại ngoại lệ? Điều gì về việc phát hành tài nguyên? Tôi nghĩ đó là một câu trả lời hay nhưng không hoàn chỉnh. Có những câu trả lời hoàn chỉnh khác ở đây. –

16

Một vấn đề là bạn đang đọc bộ đệm. Nếu mọi đọc của luồng đầu vào không phải là bội số chính xác của 1024, bạn sẽ sao chép dữ liệu xấu. Sử dụng:

byte[] buffer = new byte[1024]; 
int len1 = 0; 
while ((len1 = in.read(buffer)) != -1) { 
    f.write(buffer,0, len1); 
} 
+0

On line 4, bạn có nghĩa len1, không len? –

+0

Tôi nhìn vào ví dụ Ry4an và giả sử bạn có nghĩa là len1 - cảm ơn. –

14
public class download extends Activity { 

    private static String fileName = "file.3gp"; 
    private static final String MY_URL = "Your download url goes here"; 

    @Override 
    public void onCreate(Bundle savedInstanceState) { 
     super.onCreate(savedInstanceState); 
     setContentView(R.layout.main); 

     try { 
      URL url = new URL(MY_URL); 
      HttpURLConnection c = (HttpURLConnection) url.openConnection(); 
      c.setRequestMethod("GET"); 
      c.setDoOutput(true); 
      c.connect(); 

      String PATH = Environment.getExternalStorageDirectory() 
       + "/download/"; 
      Log.d("Abhan", "PATH: " + PATH); 
      File file = new File(PATH); 
      if(!file.exists()) { 
       file.mkdirs(); 
      } 
      File outputFile = new File(file, fileName); 
      FileOutputStream fos = new FileOutputStream(outputFile); 
      InputStream is = c.getInputStream(); 
      byte[] buffer = new byte[1024]; 
      int len1 = 0; 
      while ((len1 = is.read(buffer)) != -1) { 
       fos.write(buffer, 0, len1); 
      } 
      fos.flush(); 
      fos.close(); 
      is.close(); 
     } catch (IOException e) { 
      Log.e("Abhan", "Error: " + e); 
     } 
     Log.i("Abhan", "Check Your File."); 
    } 
} 
+0

Câu trả lời này sẽ không hoạt động. Các kết nối mạng trên luồng chính sẽ ném 'android.os.NetworkOnMainThreadException'. – JBirdVegas

+0

@JBirdVegas Không chạy hoạt động liên quan đến mạng trên chuỗi chính. Vui lòng tạo một chuỗi công nhân. –

+0

Sử dụng AsyncTask doInBackground để thực hiện mã lệnh try {}. và xóa setDoOutput (true) khỏi nó. – Nepster

2

Chỉ cần sử dụng phương pháp sao chép của apache (Apache Commons IO) - lợi thế của việc sử dụng Java!

IOUtils.copy(is, os); 

Đừng quên để đóng suối trong một khối finally:

try{ 
     ... 
} finally { 
    IOUtils.closeQuietly(is); 
    IOUtils.closeQuietly(os); 
} 
+2

Và cũng không vượt qua các luồng. –

+2

Thư viện 200k chỉ để tải xuống tệp ..... –

4

Tôi cố định mã dựa trên phản hồi trước đây về chủ đề này. Tôi đã thử nghiệm bằng cách sử dụng nhật thực và nhiều tệp lớn. Nó hoạt động tốt. Chỉ cần sao chép và dán nó vào môi trường của bạn và thay đổi đường dẫn http và vị trí bạn muốn tải xuống tệp.

try { 
    //this is the file you want to download from the remote server 
    String path ="http://localhost:8080/somefile.zip"; 
    //this is the name of the local file you will create 
    String targetFileName 
     boolean eof = false; 
    URL u = new URL(path); 
    HttpURLConnection c = (HttpURLConnection) u.openConnection(); 
    c.setRequestMethod("GET"); 
    c.setDoOutput(true); 
    c.connect(); 
    FileOutputStream f = new FileOutputStream(new File("c:\\junk\\"+targetFileName)); 
     InputStream in = c.getInputStream(); 
     byte[] buffer = new byte[1024]; 
     int len1 = 0; 
     while ((len1 = in.read(buffer)) > 0) { 
     f.write(buffer,0, len1); 
       } 
    f.close(); 
    } catch (MalformedURLException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
    } catch (ProtocolException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
    } catch (FileNotFoundException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
    } catch (IOException e) { 
    // TODO Auto-generated catch block 
    e.printStackTrace(); 
} 

Chúc may mắn Alireza Aghamohammadi

+0

theo cách này, tệp sẽ được tải xuống cùng một tệp. tôi có nghĩa là nếu tập tin đã được tải xuống nó sẽ đưa ra một cảnh báo? – Loshi

+0

xóa setDoOutput (true); từ mã – Nepster

28
new DefaultHttpClient().execute(new HttpGet("http://www.path.to/a.mp4?video")) 
     .getEntity().writeTo(
       new FileOutputStream(new File(root,"Video.mp4"))); 
+3

giải pháp một dòng. Nice – Santhosh

+1

Tôi thích một giải pháp dòng. Tuy nhiên, bạn nên kiểm tra thực thể trước khi ghi vào tệp, nếu không tệp sẽ được tạo ngay cả khi có sự cố khi tải xuống. Vì vậy, lần sau, bạn có thể thử mở một tệp bị hỏng. – thanhbinh84

+0

Làm cách nào để đặt tên tệp được tải xuống giống với tên tệp gốc động? –

Các vấn đề liên quan