2017-02-20 8 views
0

Мне нужно сохранить pdf-файл, используя байты из ответа HTTP.Пустой PDF при сохранении с okHttp

Если файл небольшой (около сотни байт, менее 1k), все в порядке, но если файл слишком велик, я видел (используя другое приложение через Intent) все страницы белого (количество страниц верное).

Я сохраняю документ во внешнем хранилище и передаю uri на намерение.

Это мой код, чтобы получить файл с сервера и сохранить его на внешнее устройство хранения:

public static Observable<Integer> getDocument(final String id, final String service, final String filename){ 
    return Observable.create(new Observable.OnSubscribe<Integer>() { 
     @Override 
     public void call(Subscriber<? super Integer> subscriber) { 
      InputStream inputStream = null; 
      FileOutputStream outputStream = null; 
      OkHttpClient client = HypeHttpClientBuilder.getOkHttpClient(200); //timeout 
      RequestBody formBody = new FormEncodingBuilder() 
        .add("platform", HypeApplication.getDeviceType()) 
        .add("function", service) 
        .add("pdfid",id) 
        .build(); 

      Request requests = HttpRequestBuilder.getRequest(formBody); 
      try { 
       Response response = client.newCall(requests).execute(); 

       inputStream = response.body().byteStream(); 
       File dir = new File(Environment.getExternalStorageDirectory(),"Hype"); 
       if (!dir.mkdirs()) { 
        Log.e(TAG, "Directory not created"); 
       } 
       outputStream = new FileOutputStream(new File(dir, filename)); 
       int totalCount = inputStream.available(); 
       byte[] buffer = new byte[1024 * 1024]; 
       int len; 
       int readLen = 0; 
       while ((len = inputStream.read(buffer)) != -1) { 

        //System.out.println("download loop " + Thread.currentThread().getName()); 

        outputStream.write(buffer, 0, len); 
        readLen += len; 

       } 


       subscriber.onNext(readLen); 


      }catch (Exception e){ 
       subscriber.onError(e); 
      }finally { 
       try { 
        if (inputStream != null) { 
         inputStream.close(); 
        } 
        if (outputStream != null) { 
         outputStream.flush(); 
         outputStream.close(); 
        } 
       } catch (IOException e) { 
        e.printStackTrace(); 
       } 
      } 

      subscriber.onCompleted(); 


     } 
    }); 
} 

и это код, чтобы начать другую деятельность:

Intent intent = new Intent(Intent.ACTION_VIEW); 
      intent.setDataAndType(FileProvider.getUriForFile(getActivity(),getActivity().getApplicationContext().getPackageName() + ".provider",f) 
        , "application/pdf"); 

      intent.setFlags(Intent.FLAG_ACTIVITY_NO_HISTORY); 
      intent.setFlags(Intent.FLAG_GRANT_READ_URI_PERMISSION); 

      startActivity(intent); 

UPDATE Я пытался используйте прокси-сервер для перехвата HTTP-вызова. Итак, я получил файл из прокси и файла, сгенерированного моим кодом, и я их сравнил: есть некоторые отличия.

Я получил простое решение, используя класс UrlConnection.

URL url = new URL(URLSetting.getOldUrl()); 
       HttpURLConnection conn = (HttpURLConnection)url.openConnection(); 
       conn.setReadTimeout(10000); 
       conn.setConnectTimeout(15000); 
       conn.setRequestMethod("POST"); 
       conn.setDoInput(true); 
       conn.setDoOutput(true); 
       conn.setRequestProperty("appversion","2.0.0"); 
       conn.setRequestProperty("Content-Type", 
         "application/x-www-form-urlencoded"); 


       Uri.Builder builder = new Uri.Builder() 
         .appendQueryParameter("platform", HypeApplication.getDeviceType()) 
         .appendQueryParameter("function", service) 
         .appendQueryParameter("deviceid",HypeApplication.getDeviceId()) 
         .appendQueryParameter("pdfid", id); 

       OutputStream os = conn.getOutputStream(); 
       BufferedWriter writer = new BufferedWriter(
         new OutputStreamWriter(os, "UTF-8")); 
       writer.write(builder.build().getEncodedQuery()); 
       writer.flush(); 
       writer.close(); 
       os.close(); 

       conn.connect(); 


       inputStream = conn.getInputStream(); 

Итак, вы знаете, если okHttp установлен как кодировка по умолчанию UTF-8?

+0

Я рекомендую 'getFD(). Sync()' между 'flush()' и 'close()' на вашем 'FileOutputStream'. Помимо этого, загрузите PDF с устройства и посмотрите, все ли в порядке. – CommonsWare

+0

Нет. Я положил 'getFD.sync()', как вы сказали мне, но я продолжаю видеть белые страницы документа. – hooloovoo

ответ

1

Я не уверен, что именно вызывает вашу проблему, но вы можете попробовать упростить свой код с помощью API Okio.

BufferedSource source = response.body().source(); 

Sink out = Okio.sink(outputFile); 
try { 
    while (!source.exhausted()) { 
    Buffer buffer = source.buffer(); 
    out.write(buffer, buffer.size()); 
    } 
} finally { 
    out.close(); 
} 

Посмотрите, если это что-то изменит.

Смежные вопросы