我有一个Android应用程序,可以在运行时下载并使用文件。该文件是有效的,因为我可以通过浏览器下载并打开它等。但是我的应用程序一直报告该文件已损坏。
经过调查,我发现服务器(我无法控制)正在返回错误的“Content-Length:”(~180 vs~120000)。标题是罪魁祸首,因为我通过使用curl下载文件来确认问题 - 这也导致了截断文件。
经过一些研究后我得出结论,我使用BufferedInputStream
附加到ByteArrayBuffer
是将字节数组自动调整为url连接内容长度。为了避免这种情况,我尝试使用ByteArrayOutputStream
代替,但这没有解决任何问题。
如果内容长度设置不正确,有人知道下载文件的方法吗?浏览器可以。
这是我最近的尝试:
public static void downloadFileFromRemoteUrl(String urlString, String destination){
try {
URL url = new URL(urlString);
File file = new File(destination);
URLConnection urlConnection = url.openConnection();
InputStream inputStream = urlConnection.getInputStream();
byte[] buffer = new byte[1024];
int curLength = 0;
int newLength = 0;
ByteArrayOutputStream byteArrayOutputStream = new ByteArrayOutputStream();
while((newLength = inputStream.read(buffer))>0)
{
curLength += newLength;
byteArrayOutputStream.write(buffer, 0, newLength);
}
FileOutputStream fos = new FileOutputStream(file);
fos.write(byteArrayOutputStream.toByteArray());
fos.close();
android.util.Log.d("DB UPDATE", "Done downloading database. Size: " + byteArrayOutputStream.toByteArray().length);
}
catch (MalformedURLException e) {
e.printStackTrace();
}
catch (IOException e) {
e.printStackTrace();
}
}
答案 0 :(得分:1)
经过一些研究后,我得出结论,我使用
BufferedInputStream
附加到ByteArrayBuffer
会将字节数组自动调整为url连接内容长度。
无意义。你正在将那些具有超自然力量的类归功于你。输出流怎么可能知道Content-length头? URLConnection
的输入流正在以内容长度终止。正确。
为了避免这种情况,我尝试使用ByteArrayOutputStream,但这没有解决任何问题。
当然不是。
如果内容长度设置不正确,有人知道下载文件的方法吗?
您可以使用Socket
并自己使用HTTP,这听起来不那么简单。但问题出在服务器上,应该在哪里修复。抱怨。或者@Zong Yu是正确的,页面是包含JavaScript的HTML,比方说。
注意您无需将整个文件读入内存:
while((newLength = inputStream.read(buffer))>0)
{
curLength += newLength;
fos.write(buffer, 0, newLength);
}
答案 1 :(得分:0)
我的最终“解决方案”是意识到我正在处理301重定向响应而不是实际资源!我更新了处理我的网址的部分,检查301以及是否存在,更新网址。新网址包含与我正在下载的文件相对应的Content-Length。
// start by creating an http url connection object
HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection();
// determine if this is a redirect
boolean redirect = false;
int status = httpURLConnection.getResponseCode();
if (status != HttpURLConnection.HTTP_OK) {
if (status == HttpURLConnection.HTTP_MOVED_TEMP
|| status == HttpURLConnection.HTTP_MOVED_PERM
|| status == HttpURLConnection.HTTP_SEE_OTHER)
redirect = true;
}
// if it is, we need a new url
if (redirect) {
String newUrl = httpURLConnection.getHeaderField("Location");
httpURLConnection = (HttpURLConnection) new URL(newUrl).openConnection();
}
答案 2 :(得分:-1)
尝试抓取。 Fetch是适用于Android的应用下载管理器。它非常易于使用。找到GitHub页面here。该项目附带了几个可以尝试的演示。免责声明:我是Fetch的创建者,它是开源的。