我写的下载文件的方法总是会产生损坏的文件。
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
命令没有类型。
你知道缺少什么以及如何解决它吗?
谢谢。
更简单的代码版本(但错误是相同的)
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
问题在于我从我的API单例中获得了OkHttpClient
,这是由改造使用并具有多个拦截器。那些拦截器污染了这种反应。
所以我OkHttpClient client = Api.getInstance().getOkHttpClient();
成了OkHttpClient client = new OkHttpClient.Builder().build();
,现在一切正常!
非常感谢。我现在正把这个方法分成小块。
答案 0 :(得分:1)
output.write(response.body().bytes());
试试这样的事情
byte[] buff = new byte[1024 * 4];
while (true) {
int byteCount = input.read(buff);
if (byteCount == -1) {
break;
}
output.write(buff, 0, byteCount);
}