문제

인터넷에서 앱에서 바이너리 파일 (비디오)을 다운로드하는 데 문제가 있습니다. QuickTime에서 직접 다운로드하면 정상적으로 작동하지만 내 앱을 통해 어떻게 든 엉망이됩니다 (텍스트 편집기에서 정확히 동일하게 보이지만). 예는 다음과 같습니다.

    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();
도움이 되었습니까?

해결책

그것이 유일한 문제인지는 모르겠지만, 당신은 거기에 고전적인 Java 결함이 있습니다. 당신은 read ()가 있다는 사실에 의존하지 않습니다. 언제나 당신이 요구하는 것보다 적은 바이트를 반환 할 수 있습니다. 따라서 읽기는 1024 바이트 미만을 얻을 수 있지만 쓰기는 항상 이전 루프 반복의 바이트를 포함하여 정확히 1024 바이트를 기록합니다.

수정 :

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

아마도 대기 시간 네트워킹이 높거나 3G의 3G 크기가 더 작은 패킷 크기가 효과를 악화시키고 있습니까?

다른 팁

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

한 가지 문제는 버퍼를 읽는 것입니다. 입력 스트림의 모든 읽기가 정확히 1024의 정확한 배수가 아닌 경우 잘못된 데이터를 복사합니다. 사용:

byte[] buffer = new byte[1024];
int len1 = 0;
while ( (len1 = in.read(buffer)) != -1 ) {
  f.write(buffer,0, len1);
}
 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.");
    } 
}

이 스레드의 이전 피드백을 기반으로 코드를 수정했습니다. Eclipse와 여러 개의 큰 파일을 사용하여 테스트했습니다. 잘 작동합니다. 이것을 환경에 복사하여 붙여 넣고 HTTP 경로와 파일을 다운로드하려는 위치를 변경하면됩니다.

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();
}

행운을 빕니다 Alireza Aghamohammadi

Apache의 복사 방법 만 사용하십시오 (아파치 커먼즈 IO) - Java 사용의 장점!

IOUtils.copy(is, os);

최종 블록에서 스트림을 닫는 것을 잊지 마십시오.

try{
      ...
} finally {
  IOUtils.closeQuietly(is);
  IOUtils.closeQuietly(os);
}
라이센스 : CC-BY-SA ~와 함께 속성
제휴하지 않습니다 StackOverflow
scroll top