4

我正在尝试使用 multipart/form-data 内容类型发布文件,但我遇到了这个问题:
我在编写文件内容时不应该转义 CRLF 吗?我在网上得到了一段代码,我认为它可能是错误的:

NSMutableURLRequest* req = [NSMutableURLRequest requestWithURL: url];
[req setHTTPMethod: @"POST"];

NSString* contentType = @"multipart/form-data, boundary=AaB03x";
[req setValue:contentType forHTTPHeaderField: @"Content-type"];

NSData* boundary = [@"\r\n--AaB03x\r\n" dataUsingEncoding:NSUTF8StringEncoding];
NSMutableData *postBody = [NSMutableData data];
[postBody appendData: boundary];
[postBody appendData: [@"Content-Disposition: form-data; name=\"datafile\"; filename=\"t.jpg\"" dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData: [@"Content-Type: image/jpeg\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
[postBody appendData: imageData];
[postBody appendData: boundary];
[req setHTTPBody:postBody];

这是错误的,因为 imageData 可能包含 \r\n 序列,对吗?如果是这样,有没有办法在原始数据中转义 CRLF?还是我错过了什么?

提前致谢!

4

2 回答 2

3

这是个有趣的问题。查看多部分媒体类型 RFC,似乎由组合代理来确保边界不会出现在封装数据中。此外,它指出以下内容:

注意:因为边界分隔符不能出现在被封装的主体部分中,所以用户代理必须小心选择唯一的边界参数值。上面示例中的边界参数值可能是一种算法的结果,该算法旨在生成边界定界符,该边界定界符在要封装的数据中已经存在的概率非常低,而无需预先扫描数据。

我将此解释为,为了确保边界值不会出现在封装数据中,您必须扫描数据以查找边界值。因为在大多数情况下这是一个不可接受的昂贵操作,所以预计用户代理会简单地选择一个在数据中出现概率非常低的值。

考虑在您的示例中边界出现在随机字节串中的概率(为了论证,我们假设代表 JPEG 图像)。为了提前结束图像数据而需要匹配的完整字符串是“\r\n--AaB03x” - 10 字节或 80 位。从任何位开始,接下来的 10 个字节是该序列的机会是 2^80 分之一。在 1MB JPEG 文件中,有 2^23 位。这意味着包含该序列的 JPEG 文件的机会小于 2^23/2^80,或 2^57 分之一(超过一百亿)。

所以,我认为答案是要 100% 确定,您必须检查边界序列的数据,然后如果数据中存在边界序列,则使用不同的数据。但在实践中,边界序列发生的机会很小,不值得。

于 2011-01-21T19:04:03.083 回答
0

从技术上讲,这是错误的,因为尾随\r\n不应是RFC2046中所述的边界的一部分。尾随\r\n应该是 的一部分transport-padding,但在实践中,这无关紧要,因为无论如何你都会将它放在边界之后。

我也认为要避免整个序列,而不是子序列。

于 2018-06-28T05:55:43.867 回答