Mã hóa URL trong Android


335

Làm thế nào để bạn mã hóa một URL trong Android?

Tôi nghĩ rằng nó là như thế này:

final String encodedURL = URLEncoder.encode(urlAsString, "UTF-8");
URL url = new URL(encodedURL);

Nếu tôi làm như trên, http://trong urlAsStringđược thay thế bởi http%3A%2F%2Ftrong encodedURLvà sau đó tôi nhận được một java.net.MalformedURLExceptionkhi tôi sử dụng địa chỉ URL.

Câu trả lời:


630

Bạn không mã hóa toàn bộ URL, chỉ một phần của URL đến từ "các nguồn không đáng tin cậy".

String query = URLEncoder.encode("apples oranges", "utf-8");
String url = "http://stackoverflow.com/search?q=" + query;

Ngoài ra, bạn có thể sử dụng String.urlEncode (Chuỗi str) của DroidParts mà không đưa ra các ngoại lệ được kiểm tra.

Hoặc sử dụng một cái gì đó như

String uri = Uri.parse("http://...")
                .buildUpon()
                .appendQueryParameter("key", "val")
                .build().toString();

1
Điều gì nếu toàn bộ url là không đáng tin cậy? Tôi có nên mã hóa mọi thứ trừ giao thức không? Tôi mong đợi một phương pháp thuận tiện để làm điều này.
hpique

5
Sau đó, nó chỉ là một url bị hỏng. Ý tưởng là để ngăn phần truy vấn phá vỡ url.
yanchenko

5
@hgpc - hãy xem phần 3 của RFC3986 ( tools.ietf.org/html/rfc3986#section-3 ). Nó cho bạn biết cách mã hóa các phần khác nhau của URI. Thật không may, mỗi phần của URI (máy chủ, đường dẫn, truy vấn, v.v.) có các quy tắc mã hóa hơi khác nhau.
D.Shawley

2
Điều này tốt ở bạn chỉ là xử lý một phần cụ thể của URL và bạn biết cách xây dựng hoặc xây dựng lại URL. Để biết cách tiếp cận tổng quát hơn có thể xử lý bất kỳ chuỗi url nào, hãy xem câu trả lời của tôi dưới đây.
Craig B

8
Tại sao tôi nhận được cảnh báo không dùng nữa? Được sử dụng Uri.encode(query);thay thế.
prasanthv

166

Tôi sẽ thêm một đề nghị ở đây. Bạn có thể làm điều này để tránh phải có bất kỳ thư viện bên ngoài.

Hãy thử xem:

String urlStr = "http://abc.dev.domain.com/0007AC/ads/800x480 15sec h.264.mp4";
URL url = new URL(urlStr);
URI uri = new URI(url.getProtocol(), url.getUserInfo(), url.getHost(), url.getPort(), url.getPath(), url.getQuery(), url.getRef());
url = uri.toURL();

Bạn có thể thấy rằng trong URL cụ thể này, tôi cần mã hóa các khoảng trắng đó để tôi có thể sử dụng nó cho một yêu cầu.

Điều này tận dụng một vài tính năng có sẵn cho bạn trong các lớp Android. Đầu tiên, lớp URL có thể ngắt một url thành các thành phần thích hợp của nó để bạn không cần phải thực hiện bất kỳ công việc tìm kiếm / thay thế chuỗi nào. Thứ hai, cách tiếp cận này tận dụng tính năng của lớp URI của các thành phần thoát đúng khi bạn xây dựng một URI thông qua các thành phần thay vì từ một chuỗi.

Cái hay của phương pháp này là bạn có thể lấy bất kỳ chuỗi url hợp lệ nào và để nó hoạt động mà không cần bất kỳ kiến ​​thức đặc biệt nào về nó.


19
Đây phải là câu trả lời chính xác. đây là cách chính thức và rõ ràng để làm điều này
Asanka Senavirathna

3
Nó cũng có thể là một ý tưởng tốt để urldecode urlStr trước khi gửi nó đến hàm tạo URL. URLDecoder.decode (urlStr)
Jakob Eriksson

1
Cảm ơn cho bài viết :) Nhưng tôi đang phải đối mặt với một vấn đề. Nếu url đã được mã hóa một phần, thì đó là mã hóa các phần đã được mã hóa. Tôi nên làm gì? Ví dụ: dj-ideo.us/Music/XinatingSinGleTrack/320%20Kbps/ợi% 20 được mã hóa thành% 2520
berserk

2
@berserk Nếu nó đã được mã hóa, đừng mã hóa nó. Bạn không nên vào trạng thái được mã hóa một phần hoặc bạn không chắc chắn liệu nó có được mã hóa hay không.
Hầu tước Lorne

3
Phương pháp này không mã hóa các ký tự như ğ đến% C4% 9F. Đã chấp nhận một mã hóa!
Alexander Prokofyev

73

Đối với Android, tôi sẽ sử dụng Chuỗi android.net.Uri.encode (Chuỗi s)

Mã hóa các ký tự trong chuỗi đã cho là '%' - các octet đã thoát bằng cách sử dụng lược đồ UTF-8. Giữ nguyên các chữ cái ("AZ", "az"), số ("0-9") và các ký tự không được kiểm soát ("_-!. ~ '() *"). Mã hóa tất cả các nhân vật khác.

Ví dụ/

String urlEncoded = "http://stackoverflow.com/search?q=" + Uri.encode(query);

2
Không may Uri.encode("a=1&b=1")sản xuất a%3D1%26b%3D1nhưng dự kiếna=1&b=1
loentar

14
@loentar Đó là kết quả mong đợi. Nếu người dùng nhập a=1&b=1dưới dạng truy vấn, bạn muốn truy vấn chính xác điều đó.
Anubian Noob

Điều này khác biệt như thế nào với URLEncoder.encode (StringHere, "UTF-8")
dòng chảy bị kẹt vào

@stuckedoverflow Vì một điều, Uri.encode (str) không ném ngoại lệ được kiểm tra không giống như URLEncoder.encode (str, "UTF-8")
deekshith

50

Ngoài ra, bạn có thể sử dụng này

private static final String ALLOWED_URI_CHARS = "@#&=*+-_.,:!?()/~'%";
String urlEncoded = Uri.encode(path, ALLOWED_URI_CHARS);

đó là phương pháp đơn giản nhất


1
đây không phải là giải pháp tốt nhất, nhưng nó chắc chắn là một cách khắc phục nhanh chóng ... thanx
Sebastian Breit

4
Đây là cách khắc phục nhanh nhất khi toàn bộ URL không đáng tin cậy. Cảm ơn!
dùng1032613

Bạn có chắc chắn nên cho phép%? Nó không nên được mã hóa?
MediumOne

1
Làm cách nào để mã hóa url này để có thể chia sẻ và sau đó người dùng có thể mở liên kết và xem trang: yazd20.com//News/2015/11/ سسنن-آب-كمدي-حسن-ريوندي-در-يز.
Ahmad Ebrahimi

3
try {
                    query = URLEncoder.encode(query, "utf-8");
                } catch (UnsupportedEncodingException e) {
                    // TODO Auto-generated catch block
                    e.printStackTrace();
                }

1

bạn có thể sử dụng các phương pháp dưới đây

public static String parseUrl(String surl) throws Exception
{
    URL u = new URL(surl);
    return new URI(u.getProtocol(), u.getAuthority(), u.getPath(), u.getQuery(), u.getRef()).toString();
}

hoặc là

public String parseURL(String url, Map<String, String> params)
{
    Builder builder = Uri.parse(url).buildUpon();
    for (String key : params.keySet())
    {
        builder.appendQueryParameter(key, params.get(key));
    }
    return builder.build().toString();
}

cái thứ hai tốt hơn cái thứ nhất


0

Tìm ký tự tiếng Ả Rập và thay thế chúng bằng mã hóa UTF-8. một số thứ như thế này:

for (int i = 0; i < urlAsString.length(); i++) {
    if (urlAsString.charAt(i) > 255) {
        urlAsString = urlAsString.substring(0, i) + URLEncoder.encode(urlAsString.charAt(i)+"", "UTF-8") + urlAsString.substring(i+1);
    }
}
encodedURL = urlAsString;
Khi sử dụng trang web của chúng tôi, bạn xác nhận rằng bạn đã đọc và hiểu Chính sách cookieChính sách bảo mật của chúng tôi.
Licensed under cc by-sa 3.0 with attribution required.