使用Universal Image Loader时出现FileNotFoundException

7
这个问题涉及到一个非常流行的Android库,Universal Image Loader for Android: https://github.com/nostra13/Android-Universal-Image-Loader
  1. 我确保已添加WRITE_EXTERNAL_STORAGE。
  2. 我启用了内存和磁盘缓存。
  3. 我使用UnlimitedDiscCache作为磁盘缓存。
  4. 我正在使用Android 2.2 SDK构建。异常是在Android 4.1.2 Nexus S设备上测试应用程序时发现的。
  5. 对于我的大部分图像,加载都很顺畅。然而,对于某些图像,我总是得到相同的异常。以下是一个例子。

图片URL: http://i10.topit.me/l046/10046137034b1c0db0.jpg

回溯信息:

01-14 00:24:42.125: 

ERROR/ImageLoader(1671): http://i10.topit.me/l046/10046137034b1c0db0.jpg

java.io.FileNotFoundException: http://i10.topit.me/l046/10046137034b1c0db0.jpg

at libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:177)

at com.nostra13.universalimageloader.core.download.URLConnectionImageDownloader.getStreamFromNetwork(URLConnectionImageDownloader.java:40)

at com.nostra13.universalimageloader.core.download.ImageDownloader.getStream(ImageDownloader.java:27)

at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.saveImageOnDisc(LoadAndDisplayImageTask.java:296)

at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.tryLoadBitmap(LoadAndDisplayImageTask.java:204)

at com.nostra13.universalimageloader.core.LoadAndDisplayImageTask.run(LoadAndDisplayImageTask.java:128)

at java.util.concurrent.Executors$RunnableAdapter.call(Executors.java:442)

请帮忙。


只是一个猜测,但这些图像可能需要代理才能访问,我记得在API级别8中有代理问题。 - Boris Strandjev
不太可能。所有的图片都托管在同一台服务器上。其中大部分可以在我的测试安卓设备上轻松下载。 - Di Wu
我访问那个页面时出现了404错误(这会导致文件未找到),尽管404页面只是一个位于http://img.topit.me/404.jpg的图片,上面写着(love)it.me。 - Joseph Earl
现在我不再使用这个。请使用一个更好的图像服务器。 - Joseph Earl
4个回答

12

跟进:

最终我解决了我的问题,而不需要更改服务器代码。我所做的是将默认的URLConnectionImageDownloader替换为HttpClientImageDownloader

代码示例:

        HttpParams params = new BasicHttpParams();
        // Turn off stale checking. Our connections break all the time anyway,
        // and it's not worth it to pay the penalty of checking every time.
        HttpConnectionParams.setStaleCheckingEnabled(params, false);
        // Default connection and socket timeout of 10 seconds. Tweak to taste.
        HttpConnectionParams.setConnectionTimeout(params, 10 * 1000);
        HttpConnectionParams.setSoTimeout(params, 10 * 1000);
        HttpConnectionParams.setSocketBufferSize(params, 8192);

        // Don't handle redirects -- return them to the caller. Our code
        // often wants to re-POST after a redirect, which we must do ourselves.
        HttpClientParams.setRedirecting(params, false);
        // Set the specified user agent and register standard protocols.
        HttpProtocolParams.setUserAgent(params, "some_randome_user_agent");
        SchemeRegistry schemeRegistry = new SchemeRegistry();
        schemeRegistry.register(new Scheme("http", PlainSocketFactory.getSocketFactory(), 80));
        schemeRegistry.register(new Scheme("https", SSLSocketFactory.getSocketFactory(), 443));

        ClientConnectionManager manager = new ThreadSafeClientConnManager(params, schemeRegistry);


        ImageLoaderConfiguration config =
                new ImageLoaderConfiguration
                        .Builder(MainActivity.sharedMainActivity.getApplicationContext())
                        .defaultDisplayImageOptions(defaultOptions)
                        .discCache(new UnlimitedDiscCache(cacheDir))
                        .threadPoolSize(1)
                        .memoryCache(new WeakMemoryCache())
                        .imageDownloader(new HttpClientImageDownloader(new DefaultHttpClient(manager, params)))
                        .build();

:)


5
非常感谢!这对我很有帮助。在代码中只需要补充最后一行的上下文信息:.imageDownloader(new HttpClientImageDownloader(msContext, new DefaultHttpClient(manager, params))) - David
@DiWu 抱歉,朋友,我遇到了同样的问题。但是我正在使用最新版本的UIML。你在哪个类中进行了这些更改? URLConnectionImageDownloader和HttpClientImageDownloader 包和类的名称是什么? - B.rohit Nare
03-09 18:12:59.535: E/ImageLoader(9878): java.io.FileNotFoundException: http://www.dakabo.dk/images/phocagallery/Levende_vaerksted/dsc09327.jpg%20 03-09 18:12:59.535: E/ImageLoader(9878): 在 libcore.net.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:194) 中 03-09 18:12:59.535: E/ImageLoader(9878): 在 com.nostra13.universalimageloader.core.download.BaseImageDownloader.getStreamFromNetwork(BaseImageDownloader.java:124) 中 - B.rohit Nare
无法实现此功能。HttpClientImageDownloader类是什么?请帮忙。 - umesh lohani
我无法实现这个HttpClientImageDownloader,如何让它工作? - satryaway
显示剩余3条评论

4

寻找libcore.net.http.HttpURLConnectionImpl.getInputStream()的实现

 @Override
    public InputStream getInputStream() throws IOException {
        if (!doInput) {
            throw new ProtocolException("This protocol does not support input");
        }

        retrieveResponse();

        /*
         * if the requested file does not exist, throw an exception formerly the
         * Error page from the server was returned if the requested file was
         * text/html this has changed to return FileNotFoundException for all
         * file types
         */
        if (responseCode >= HTTP_BAD_REQUEST) {
            throw new FileNotFoundException(url.toString());
        }

        if (responseBodyIn == null) {
            throw new IOException("No response body exists; responseCode=" + responseCode);
        }

        return responseBodyIn;
    }

根据此,即使出现服务器错误或未经授权,也可能会抛出FileNotFoundException。
我没有找到HTTP_BAD_REQUEST的值,但它始终为400。源代码链接 http://www.java2s.com/Open-Source/Android/android-core/platform-libcore/org/apache/harmony/luni/internal/net/www/protocol/http/HttpURLConnectionImpl.java.htm

1
如果您访问该地址,您会发现有这样的文件:http://i10.topit.me/l046/10046137034b1c0db0.jpg - Boris Strandjev
是的,我刚刚做了它。似乎出现了一些奇怪的情况。但堆栈跟踪明确表明文件未找到。 - Viacheslav
1
有时服务器确实会响应404(实际上在几次成功响应后它会持续响应404)。因此,这不是UIL的问题。 - nostra13
有没有解决方案? - Gaurav Vashisth

0

这个配置调整是定制的。您可以调整每个选项,也可以只调整其中一些选项,或者您可以通过 ImageLoaderConfiguration.createDefault(this); 方法创建默认配置。

 public static void initImageLoader(Context context) {

    ImageLoaderConfiguration.Builder config = new ImageLoaderConfiguration.Builder(context);
    config.threadPriority(Thread.NORM_PRIORITY - 2);
    config.denyCacheImageMultipleSizesInMemory();
    config.diskCacheFileNameGenerator(new Md5FileNameGenerator());
    config.diskCacheSize(50 * 1024 * 1024); // 50 MiB
    config.tasksProcessingOrder(QueueProcessingType.LIFO);
    config.writeDebugLogs(); // Remove for release app

    // Initialize ImageLoader with configuration.
    ImageLoader.getInstance().init(config.build());
}

希望这能帮到任何人。


0

你唯一能做的就是通过L.disableLogging()来完全禁用日志记录。或者根据你的需求更改源代码。

来源:这个问题的nostra13答案

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接