我编写的下载文件的方法总是会产生损坏的文件。
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
命令。
您知道缺少什么以及如何修复它吗?
谢谢。
Edit
代码的简单版本(但错误是相同的)
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
Solution
问题是我得到了OkHttpClient
来自我的 API 单例,它被改造使用并且有多个拦截器。这些拦截器正在污染响应。
So I OkHttpClient client = Api.getInstance().getOkHttpClient();
became OkHttpClient client = new OkHttpClient.Builder().build();
现在一切都好了!
多谢。我现在正在将该方法分成更小的部分。