Метод, который я написал для загрузки файлов, всегда создает поврежденные файлы.Загрузка поврежденных файлов с помощью OkHttp
public static String okDownloadToFileSync(final String link, final String fileName, final boolean temp, DownloadStatusManager statusManager, ErrorDisplayerInterface errorDisplayerInterface) {
Request request = new Request.Builder()
.url(link)
.build();
OkHttpClient client = Api.getInstance().getOkHttpClient();
OutputStream output = null;
InputStream input = null;
try {
Response response = client.newCall(request).execute();
//Add the file length to the statusManager
final int contentLength = Integer.parseInt(response.header("Content-Length"));
if (statusManager != null) {
statusManager.add(Hash.md5(link), contentLength);
}
//Get content type to know extension
final String contentType = response.header("Content-Type");
final String ext = contentTypeMap.get(contentType);
Log.i(TAG, link + "\n --> contentType = " + contentType + "\n --> ext = " + ext);
if (ext == null) {
Log.e(TAG, "-----------\next is null, seems like there is a problem with that url : \n " + link + "\n----------");
return null;
} else if (ext.equals("json")) {
Log.e(TAG, "-----------\ndownloadable file seems to be a json, seems like there is a problem with that url : \n " + link + "\n----------");
return null;
}
//Check if file already exists
if (!temp && fileName != null) {
File test = new File(M360Application.getContext().getFilesDir(), fileName + "." + ext);
if (test.exists()) {
Log.i(TAG, "File exists ! : " + test.getPath());
test.delete();
//return test.getAbsolutePath();
}
}
// expect HTTP 200 OK, so we don't mistakenly save error report instead of the file
if (!response.isSuccessful()) {
errorDisplayerInterface.popWarn(null, "Error while downloading " + link, "connection.getResponseCode() != HttpURLConnection.HTTP_OK");
return null;
}
input = response.body().byteStream();
File file;
if (temp) {
file = File.createTempFile(UUID.randomUUID().toString(), ext, M360Application.getContext().getCacheDir());
} else {
file = new File(M360Application.getContext().getFilesDir(), fileName + "." + ext);
}
output = new FileOutputStream(file);
output.write(response.body().bytes());
// byte data[] = new byte[4096];
// long total = 0;
// int count;
// while ((count = input.read(data)) != -1) {
// output.write(data, 0, count);
// total++;
//
// if (statusManager != null) {
// statusManager.update(Hash.md5(link), contentLength - total);
// }
// }
return file.getAbsolutePath();
} catch (IOException e) {
e.printStackTrace();
errorDisplayerInterface.popError(null, e);
} finally {
if (statusManager != null) {
statusManager.finish(Hash.md5(link));
}
try {
if (output != null)
output.close();
if (input != null)
input.close();
} catch (IOException ignored) {
ignored.printStackTrace();
}
}
return null;
}
я получить доступ к этим файл с помощью ADB, передать их на мой sccard, и я вижу, что они, кажется, правильный размер, но не имеет типа в соответствии, например, Linux file
команды.
Знаете ли вы, чего не хватает и как его исправить?
спасибо.
Редактировать
Simpler версии коды (но ошибка такой же)
public static String okioDownloadToFileSync(final String link, final String fileName) throws IOException {
Request request = new Request.Builder()
.url(link)
.build();
OkHttpClient client = Api.getInstance().getOkHttpClient();
Response response = client.newCall(request).execute();
final int contentLength = Integer.parseInt(response.header("Content-Length"));
//Get content type to know extension
final String contentType = response.header("Content-Type");
final String ext = contentTypeMap.get(contentType);
// expect HTTP 200 OK, so we don't mistakenly save error report instead of the file
if (!response.isSuccessful()) {
return null;
}
File file = new File(M360Application.getContext().getFilesDir(), fileName + "." + ext);
BufferedSink sink = Okio.buffer(Okio.sink(file));
sink.writeAll(response.body().source());
sink.close();
Log.i(TAG, "file.length : " + file.length() + " | contentLength : " + contentLength);
return file.getAbsolutePath();
}
Журнал:
file.length : 2485394 | contentLength : 1399242
Решение
Проблема заключалась в том, что я получал OkHttpClient
от моего синглтона API, который использовался в модификации и имел перехватчики с множественным числом. Эти перехватчики загрязняли реакцию.
Итак, я OkHttpClient client = Api.getInstance().getOkHttpClient();
стал OkHttpClient client = new OkHttpClient.Builder().build();
, и все в порядке!
Большое спасибо. Сейчас я деля метод на более мелкие куски.
Так как намек: от «чистого качества кода» точки зрения ... Вы можете сделать много вещей, чтобы улучшить этот код; начиная с удаления отходов (например, прокомментированного кода) и уделения большего внимания правилу «одного слоя абстракции» - вы просто делаете слишком много вещей в этом одном плохом методе. Наконец: прочитайте о try-with-resources. Это спасет вас от окончательной проверки. – GhostCat
'они, похоже, имеют правильный размер'. Казаться? Разве вы даже не знаете, равен ли размер? К последнему байту? – greenapps
Здравствуйте, спасибо за отзыв! Прокомментированный код там, чтобы показать вам, что там я попытался умножить способ подачи файла. Что касается правила одиночной абстракции, что бы вы посоветовали двигаться? Я чувствую, что единственное, что делает этот метод, это загрузка файла, я не вижу, что я могу извлечь. Никогда не слышал о пробных ресурсах, я читаю это немедленно. @greenapps Как я написал, я понял, что я только проверял размер КБ, а не так, как вы заявили его «до последнего байта», в настоящее время я исправляю этот факт. –