在android下载unicode文件名的文件?

时间:2015-03-16 09:11:15

标签: unicode-string

我必须从包含以下内容的网址下载文件:

https://www.k4health.org/sites/default/files/প্রসব জনতি ফিস্টুলা চিহ্নিত করার চেকলিস্ট H11.pdf

我在编写URL之前尝试编码文件名,但它不起作用。该文件在我的SD卡中创建,但是有0个字节。这是我尝试的方式:

public String saveResourcesToSDCard(Resource res) {
    String filepath = null;
    String respath = "/bccp/" + bookID + "/resources/";
    StringBuilder sb = new StringBuilder();
    try {
        sb.append(Constant.RESOURCE_FTP);
        sb.append(new String(res.filename.getBytes(),"UTF-8"));
        URL url = new URL(sb.toString());
        //URL url = new URL(res.res_url);

        HttpURLConnection urlConnection = (HttpURLConnection) url
                .openConnection();
        urlConnection.setRequestMethod("GET");
        urlConnection.setDoOutput(true);
        urlConnection.connect();
        if(createDirIfNotExists(respath)){

            String filename = new String(res.filename.getBytes(),"UTF-8");
            Log.v("Local filename:", " " + filename);
            File file = new File(SDCardRoot, filename);
            if (file.createNewFile()) {
                file.createNewFile();
            }
            FileOutputStream fileOutput = new FileOutputStream(file);
            InputStream inputStream = urlConnection.getInputStream();

            int totalSize = urlConnection.getContentLength();
            int downloadedSize = 0;
            byte[] buffer = new byte[1024];
            int bufferLength = 0;
            while ((bufferLength = inputStream.read(buffer)) > 0) {
                fileOutput.write(buffer, 0, bufferLength);
                downloadedSize += bufferLength;
                Log.v("Progress:", "DownloadedSize: " + downloadedSize
                        + " TotalSize: " + totalSize);
            }
            fileOutput.close();
            if (downloadedSize == totalSize){
                filepath = file.getPath();
            }
        }
    } catch (MalformedURLException e) {
        e.printStackTrace();
        restartTask();
    } catch (IOException e) {
        filepath = null;
        restartTask();
        e.printStackTrace();
    }
    Log.v("filepath:", " " + filepath);
    return filepath;
}

这是logcat:

03-16 16:38:25.478: W/System.err(21199): java.net.ProtocolException: Unexpected status line: <html>
03-16 16:38:25.480: W/System.err(21199):    at com.android.okhttp.internal.http.RawHeaders.setStatusLine(RawHeaders.java:108)
03-16 16:38:25.480: W/System.err(21199):    at com.android.okhttp.internal.http.RawHeaders.fromBytes(RawHeaders.java:308)
03-16 16:38:25.481: W/System.err(21199):    at com.android.okhttp.internal.http.HttpTransport.readResponseHeaders(HttpTransport.java:135)
03-16 16:38:25.482: W/System.err(21199):    at com.android.okhttp.internal.http.HttpEngine.readResponse(HttpEngine.java:644)
03-16 16:38:25.483: W/System.err(21199):    at com.android.okhttp.internal.http.HttpURLConnectionImpl.execute(HttpURLConnectionImpl.java:347)
03-16 16:38:25.483: W/System.err(21199):    at com.android.okhttp.internal.http.HttpURLConnectionImpl.getResponse(HttpURLConnectionImpl.java:296)
03-16 16:38:25.484: W/System.err(21199):    at com.android.okhttp.internal.http.HttpURLConnectionImpl.getInputStream(HttpURLConnectionImpl.java:179)
03-16 16:38:25.484: W/System.err(21199):    at com.android.okhttp.internal.http.HttpsURLConnectionImpl.getInputStream(HttpsURLConnectionImpl.java:246)
03-16 16:38:25.486: W/System.err(21199):    at com.eatl.bdtoolkits.parsers.xmlparser.downloader.ResourceDownloader.saveResourcesToSDCard(ResourceDownloader.java:68)
03-16 16:38:25.486: W/System.err(21199):    at com.eatl.bdtoolkits.parsers.xmlparser.downloader.ResourceDownloader$DownloadResourceTask.doInBackground(ResourceDownloader.java:127)
03-16 16:38:25.487: W/System.err(21199):    at com.eatl.bdtoolkits.parsers.xmlparser.downloader.ResourceDownloader$DownloadResourceTask.doInBackground(ResourceDownloader.java:1)
03-16 16:38:25.487: W/System.err(21199):    at android.os.AsyncTask$2.call(AsyncTask.java:288)
03-16 16:38:25.488: W/System.err(21199):    at java.util.concurrent.FutureTask.run(FutureTask.java:237)
03-16 16:38:25.489: W/System.err(21199):    at android.os.AsyncTask$SerialExecutor$1.run(AsyncTask.java:231)
03-16 16:38:25.490: W/System.err(21199):    at java.util.concurrent.ThreadPoolExecutor.runWorker(ThreadPoolExecutor.java:1112)
03-16 16:38:25.491: W/System.err(21199):    at java.util.concurrent.ThreadPoolExecutor$Worker.run(ThreadPoolExecutor.java:587)
03-16 16:38:25.491: W/System.err(21199):    at java.lang.Thread.run(Thread.java:841)

我错过了什么?

2 个答案:

答案 0 :(得分:1)

https://www.k4health.org/sites/default/files/প্রসব জনতি ফিস্টুলা চিহ্নিত করার চেকলিস্ট H11.pdf

这不是一个URI。它几乎是IRI,它可以包含非ASCII字符,但不完全是因为它的空格对URI和IRI都无效。

您需要对文件名进行URL编码(使用IRI指定的非ASCII字符的UTF-8编码)

String encoded_name = URLEncoder.encode("প্রসব জনতি ফিস্টুলা চিহ্নিত করার চেকলিস্ট H11.pdf", "utf-8")
                      .replaceAll("\\+", "%20")
String url = "https://www.k4health.org/sites/default/files/" + encoded_name;

以有效的URI结尾:

https://www.k4health.org/sites/default/files/%E0%A6%AA%E0%A7%8D%E0%A6%B0%E0%A6%B8%E0%A6%AC%20%E0%A6%9C%E0%A6%A8%E0%A6%A4%E0%A6%BF%20%E0%A6%AB%E0%A6%BF%E0%A6%B8%E0%A7%8D%E0%A6%9F%E0%A7%81%E0%A6%B2%E0%A6%BE%20%E0%A6%9A%E0%A6%BF%E0%A6%B9%E0%A7%8D%E0%A6%A8%E0%A6%BF%E0%A6%A4%20%E0%A6%95%E0%A6%B0%E0%A6%BE%E0%A6%B0%20%E0%A6%9A%E0%A7%87%E0%A6%95%E0%A6%B2%E0%A6%BF%E0%A6%B8%E0%A7%8D%E0%A6%9F%20H11.pdf

(请注意,用+替换%20是必要的,因为Java URLEncoder实际上是URL查询字符串中HTML表单的编码器,其中+对于空格是首选。这不适用于需要明确%20的路径。)

答案 1 :(得分:-1)

我通过这样做得到了解决方案:

public String saveResourcesToSDCard(Resource res) {
    String filepath = null;
    String respath = "/bccp/" + bookID + "/resources/";
    StringBuilder sb = new StringBuilder();
    try {
        sb.append(Constant.RESOURCE_FTP);
        String resfile = URLEncoder.encode(res.filename, "utf-8");
        String newfile = StringUtils.replace(resfile, "+", "%20");
        sb.append(newfile);
        Log.i("URL:", " " + sb.toString());
        URL url = new URL(sb.toString());
        HttpURLConnection urlConnection = (HttpURLConnection) url
                .openConnection();
        urlConnection.setRequestMethod("GET");
        urlConnection.setDoOutput(true);
        urlConnection.connect();

        if(createDirIfNotExists(respath)){

            String filename = res.filename;
            Log.i("Local filename:", " " + filename);
            Log.i("URL:", " " + sb.toString());
            File file = new File(SDCardRoot, filename);
            if (file.createNewFile()) {
                file.createNewFile();
            }
            FileOutputStream fileOutput = new FileOutputStream(file);
            InputStream inputStream = urlConnection.getInputStream();

            int totalSize = urlConnection.getContentLength();
            int downloadedSize = 0;
            byte[] buffer = new byte[1024];
            int bufferLength = 0;
            while ((bufferLength = inputStream.read(buffer)) > 0) {
                fileOutput.write(buffer, 0, bufferLength);
                downloadedSize += bufferLength;
                Log.v("Progress:", "DownloadedSize: " + downloadedSize
                        + " TotalSize: " + totalSize);
            }
            fileOutput.close();
            if (downloadedSize == totalSize){
                filepath = file.getPath();
            }
        }
    } catch (MalformedURLException e) {
        e.printStackTrace();
        //restartTask();
    } catch (IOException e) {
        filepath = null;
        //restartTask();
        e.printStackTrace();
    }
    Log.v("filepath:", " " + filepath);
    return filepath;
}