Trên thực tế, tất cả các câu trả lời trước chứa ít nhất một số không chính xác, mà đối với nhiều giá trị chung của người sử dụng được cung cấp văn bản trong Trường văn bản sẽ không giao tiếp chính xác với máy chủ
stringByAddingPercentEscapesUsingEncoding:
trăm thoát tất cả các ký tự không phải là URL hợp lệ nhân vật. Phương pháp này sẽ áp dụng một lần cho toàn bộ URL.
Câu trả lời trước cho rằng stringByAddingPercentEscapesUsingEncoding:
hoạt động giống như các lớp xây dựng URL bằng nhiều ngôn ngữ kịch bản, nơi bạn không nên áp dụng nó cho toàn bộ chuỗi URL, nhưng không. Bất kỳ ai cũng có thể dễ dàng xác minh điều này bằng cách kiểm tra kết quả đầu ra của nó cho các ảnh chưa được thoát &
s và ?
s. Vì vậy, nó là tốt để áp dụng cho toàn bộ chuỗi, nhưng nó là không đủ để áp dụng cho nội dung url 'động' của bạn.
Câu trả lời trước là đúng trong đó bạn phải thực hiện thêm một số công việc cho tên và giá trị đi vào chuỗi truy vấn CGI của bạn. Vì CGI được chỉ định bởi RFC3875, điều này thường được gọi là RFC3875 phần trăm thoát.Nó làm cho chắc chắn rằng tên và giá trị của bạn không chứa các ký tự có ký tự URL hợp lệ nhưng đó là quan trọng trong các bộ phận khác của URL (;
, ?
, :
, @
, &
, =
, $
, +
, {
, }
, <
, >
và ,
)
Tuy nhiên, điều rất quan trọng cũng là hoàn thành bằng cách làm phần trăm URL thoát trên chuỗi đầy đủ để đảm bảo rằng tất cả ký tự trong chuỗi là các ký tự URL hợp lệ. Mặc dù bạn không có trong ví dụ của mình, nói chung có thể có các ký tự trong phần 'tĩnh' của chuỗi không phải là các ký tự URL hợp lệ, do đó bạn cũng cần phải thoát khỏi các ký tự đó.
Thật không may, NSString
không cung cấp cho chúng tôi sức mạnh để thoát khỏi RFC3875 nhân vật quan trọng vì vậy chúng tôi phải nhúng xuống thành CFString
để làm như vậy. Rõ ràng sử dụng CFString
là một nỗi đau vì vậy tôi thường thêm một Category
vào NSString
như vậy:
@interface NSString (RFC3875)
- (NSString *)stringByAddingRFC3875PercentEscapesUsingEncoding:(NSStringEncoding)encoding;
@end
@implementation NSString (RFC3875)
- (NSString *)stringByAddingRFC3875PercentEscapesUsingEncoding:(NSStringEncoding)encoding {
CFStringEncoding cfEncoding = CFStringConvertNSStringEncodingToEncoding(encoding);
NSString *rfcEscaped = (NSString *)CFURLCreateStringByAddingPercentEscapes(
NULL,
(CFStringRef)self,
NULL,
(CFStringRef)@";/?:@&=$+{}<>,",
cfEncoding);
return [rfcEscaped autorelease];
}
@end
Với Category
này tại chỗ, vấn đề gốc có thể được giải quyết một cách chính xác như sau:
NSString *urlEscapedBase = [@"http://server.com/file.php" stringByAddingPercentEscapesUsingEncoding:
NSUTF8StringEncoding];
NSString *rfcEscapedName = [nameField.text stringByAddingRFC3875PercentEscapesUsingEncoding:
NSUTF8StringEncoding];
NSString *rfcEscapedTags = [tagsField.text stringByAddingRFC3875PercentEscapesUsingEncoding:
NSUTF8StringEncoding];
NSString *rfcEscapedEntry = [dreamEntry.text stringByAddingRFC3875PercentEscapesUsingEncoding:
NSUTF8StringEncoding];
NSString *urlStr = [NSString stringWithFormat:@"%@?name=%@&tags=%@&entry=%@",
urlEscapedBase,
rfcEscapedName,
rfcEscapedTags,
rfcEscapedEntry];
NSURL *url = [NSURL URLWithString:urlStr];
này một chút biến nặng chỉ rõ ràng hơn. Cũng lưu ý rằng danh sách biến được cung cấp cho stringWithFormat:
không được là nil
bị chấm dứt. Chuỗi định dạng mô tả số lượng biến chính xác cần theo dõi. Ngoài ra, về mặt kỹ thuật, các chuỗi cho các tên chuỗi truy vấn (tên, thẻ, mục nhập, ..) phải được chạy thông qua stringByAddingPercentEscapesUsingEncoding:
như một vấn đề, nhưng trong ví dụ nhỏ này, chúng ta có thể dễ dàng thấy rằng chúng không chứa các ký tự URL không hợp lệ.
Để xem lý do tại sao các giải pháp trước đó không chính xác, hãy tưởng tượng văn bản nhập của người dùng trong dreamEntry.text
có chứa &
, điều này không có khả năng xảy ra. Với các giải pháp trước đó, tất cả văn bản theo sau ký tự đó sẽ bị mất khi máy chủ nhận được văn bản đó, vì ký tự không thoát và sẽ được máy chủ giải thích là kết thúc phần giá trị của cặp chuỗi truy vấn đó.
điểm hehe. cảm ơn! – bcsantos