NSURLRequest上传多个文件 [英] NSURLRequest Upload Multiple Files

查看:101
本文介绍了NSURLRequest上传多个文件的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

我正在尝试使用POST请求将多个文件上传到服务器,但是由于某种原因,仅提交了一个文件.我怀疑边界做错了,但是我不确定在哪里...

I'm trying to upload multiple files to a server using a POST request, but for some reason, only one file is submitted. I suspect I'm doing something wrong with the boundary, but I'm not sure where...

我的代码怎么了?

    [_serverRequest setHTTPMethod:@"POST"];

    NSString *_boundary = @"14737809831466499882746641449";

    NSString *_contentType = [NSString stringWithFormat:@"multipart/form-data; charset=UTF-8; boundary=%@",_boundary];
    [_serverRequest setValue:_contentType forHTTPHeaderField:@"Content-Type"];

    /* reqeuest body */
    NSMutableData *_requestBody = [NSMutableData data];

    for (id _instance in self.currentBrowserInstances)
    {
        if ([_instance respondsToSelector:@selector(pathToDatabase)])
        {
            NSString *_databasePath = [_instance pathToDatabase];

            NSMutableString *_filename = [NSMutableString stringWithString:[self _generatedFilename]];
            [_filename appendFormat:@"_%@", [[_instance name] stringByReplacingOccurrencesOfString:@" " withString:@""]];

            if (_databasePath.pathExtension.length > 0)
                [_filename appendFormat:@".%@", _databasePath.pathExtension];

            /* Build Request Body */
            [_requestBody appendData:[[NSString stringWithFormat:@"--%@\r\n", _boundary] dataUsingEncoding:NSUTF8StringEncoding]];
            [_requestBody appendData:[[NSString stringWithFormat:@"Content-Disposition: multipart/form-data; name=\"databases\"; filename=\"%@\"\r\n", _filename] dataUsingEncoding:NSUTF8StringEncoding]];
            [_requestBody appendData:[@"Content-Type: application/octet-stream\r\n\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
            [_requestBody appendData:[NSData dataWithContentsOfFile:_databasePath]];
            [_requestBody appendData:[@"\r\n" dataUsingEncoding:NSUTF8StringEncoding]];
        }
    }

    [_requestBody appendData:[[NSString stringWithFormat:@"--%@--\r\n", _boundary] dataUsingEncoding:NSUTF8StringEncoding]];

    [_serverRequest setHTTPBody:_requestBody];

这是服务器响应:

Array
(
    [databases] => Array
        (
            [name] => QTSKUFJM_test.dat
            [type] => application/octet-stream
            [tmp_name] => /private/var/tmp/php3w7qd5
            [error] => 0
            [size] => 64576
        )
)

推荐答案

最后一个多部分之后的最终定界符(封装边界")与主体部分 plus 两个连字符相同

The final delimiter (the "encapsulation boundary") following the last multipart, is the same as for a body parts plus two hyphens.

因此,最终的定界符如下所示:

Thus, the final delimiter looks as follows:

--<boundary>--

而不是

--<boundary>--<boundary>--

与您的实现相同;)

最后一个定界符后面的CRLF也不会受到伤害.

A CRLF following the last delimiter won't hurt, also.

multipart/form-data的相应规范是"HTML中基于表单的文件上传" RFC 1867 RFC 2388 .

The corresponding specification of a multipart/form-data is "Form-based File Upload in HTML" RFC 1867 and RFC 2388.

multipart媒体类型在 RFC 2046 中被更精确地定义(该文件淘汰了RFC 1521,RFC 1522 ,RFC 1590).

The multipart media type is defined more precisely in RFC 2046 (which obsoletes RFC 1521, RFC 1522, RFC 1590).

以下是RFC 2388和RFC 2046的相关摘录:

The following are relevant excerpts from RFC 2388 and RFC 2046:

根据RFC 2388,multipart/form-data包含一系列部分.每个部分必须包含一个特定的 内容处置标头(请参阅 RFC 2183 ),其中处置类型 是"form-data",并且处置具有"name"的附加参数.例如:

According RFC 2388, a multipart/form-data contains a series of parts. Each part must contain a particular content-disposition header (see RFC 2183) where the disposition type is "form-data" and where the disposition has an additional parameter of "name". For example:

Content-Disposition: form-data; name="user"

注意:在 RFC 2231 中定义了用于内容处置标头的最新RFC. (更新:2045、2047、2183;已淘汰RFC 2184).

Note: The most recent RFC for content-disposition header is defined in RFC 2231 (Updates: 2045, 2047, 2183; Obsoletes RFC 2184)).

媒体类型multipart/form-data严格遵循所有 multipart MIME数据流的规则:

The media-type multipart/form-data strictly follows the rules of all multipart MIME data streams:

多部分"类型的子类型必须使用相同的语法.子类型的语义可能有所不同, 并且可能会对语法施加其他限制,但必须符合以下要求的语法 多部分"类型.

Subtypes of the "multipart" type must use an identical syntax. Subtypes may differ in their semantics, and may impose additional restrictions on syntax, but must conform to the required syntax for the "multipart" type.

基本上,多部分 body 必须包含一个或多个 body部分,每个部分前均带有边界定界符行, 最后一个,后跟闭合边界定界线.

Basically, the body of a multipart must contain one or more body parts, each preceded by a boundary delimiter line, and the last one followed by a closing boundary delimiter line.

每个正文部分均由标头区域空白行正文区域组成. 页眉区域 允许为空.

Each body part consists of a header area, a blank line, and a body area. The header area is allowed to be empty.

注意:主体部分是实体,而不是RFC 882 消息.也就是说,实际上没有标题 必需在身体部位.如果没有Content-Type标头,通常表示 相应的正文的内容类型为文本/纯文本; charset = US-ASCII".

Note: a body part is an entity, and not a RFC 882 message. That is, no headers are actually required in body parts. The absence of a Content-Type header usually indicates that the corresponding body has a content-type of "text/plain; charset=US-ASCII".

如果要传输文件的内容,则应将"Content-Type"设置为文件的媒体类型, 如果已知,则为"application/octet-stream".

If the contents of a file is to be transfered, then "Content-Type" shall be set to the file's media type, if known, otherwise "application/octet-stream".

提示:唯一定义了身体部位含义的标头字段是那些名称相同的字段 以"Content-"开头.其他所有标题字段在正文部分都可以忽略.

Hint: The only header fields that have defined meaning for body parts are those whose names begin with "Content-". All other header fields may be ignored in body parts.

注意:如果由于一次输入表单而要返回多个文件,则它们 应该表示为嵌入在multipart/form-data中的multipart/mixed零件.

Note: If multiple files are to be returned as the result of a single form entry, they should be represented as a multipart/mixed part embedded within the multipart/form-data.

原始本地文件名也可以作为文件名"参数提供 "content-disposition:form-data"标头的标题,如果有多个文件,则在 子部分的内容处置:文件"标头.

The original local file name may be supplied as well, either as a "filename" parameter either of the "content-disposition: form-data" header or, in the case of multiple files, in a "content-disposition: file" header of the subpart.

multipart媒体类型的通用语法在RFC 2046§5.1.1

The common syntax for the multipart media type is defined in RFC 2046 § 5.1.1

这是一种简化的更全面的形式:

Here is a simplified more comprehensive form:

多部分必须具有内容类型.例如:

A multipart must have a Content-Type. For example:

 Content-Type: multipart/subtype; boundary=gc0p4Jq0M2Yt08j34c0p

对于边界存在某些限制(请参阅RFC 2046).实际上,将其括在双引号中会使它更强大:

For the boundary there are certain limitations (please see RFC 2046). In practice, enclosing it in double quotes makes it more robust:

 Content-Type: multipart/subtype; boundary="---- boundary which requires quotes -----"

每个部分前面都有一个边界定界符.边界定界符务必出现在 行的开头(即跟随CRLF).从概念上讲,CRLF属于 边界,而不是前一个元素:

Each part is preceded by a boundary delimiter. The boundary delimiter MUST occur at the beginning of a line (that is, following a CRLF). Conceptually, the CRLF belongs to the boundary, rather to the preceding element:

boundary-delimiter :=     CRLF "--" boundary 

注意:边界后可能跟随零个或多个空格,该空格未显示在 这个BNF.

Note: the boundary may be followed by zero or more whitespace, which is not shown in this BNF.

多部分主体由一个或多个封装后跟一个闭合定界符组成:

A multipart body consists of one or more encapsulations followed by a closing delimiter:

multipart-body :=         +encapsulation
                          end-boundary-delimiter

其中封装是边界定界符,后跟CRLF,后跟主体部分:

where an encapsulation is a boundary delimiter followed by a CRLF followed by the body part:

encapsulation :=          boundary-delimiter CRLF 
                          body-part

主体部分(实体)由实体标题和主体组成:

The body part (the entity) consists of entity-headers and the body:

body-part :=              MIME-part-headers [CRLF *OCTET]

注意::实体标头(MIME部分标头)将由CRLF分隔,就像其他标头一样.

Note: An entity-header (a MIME-part-header) will be delimited by a CRLF - as any other header.

最后一部分后面是结束定界符:

end-boundary-delimiter := CRLF "--" boundary "--"


警告:

尽管有大量论文,但对边界的上述定义仍然不清楚-即使不是模棱两可!


Caution:

Despite the massive amount of papers, the above definition for boundaries is still unclear - if not ambiguous!

在RFC 2046中,第5.1.1节通用语法"规定:

In RFC 2046, § 5.1.1 Common Syntax, it states:

然后它(边界)被另一个CRLF终止,并且 下一部分的标题字段,或两个CRLF,在这种情况下 下一部分没有标题字段.

It (the boundary) is then terminated by either another CRLF and the header fields for the next part, or by two CRLFs, in which case there are no header fields for the next part.

从概念上讲,边界定界线之前的CRLF是 附加到边界...

The CRLF preceding the boundary delimiter line is conceptually attached to the boundary...

一个身体部位可能完全是空的(根据BNF).边界将是 然后是 one CRLF,然后是边界定界符或结束边界定界符.仅由于下一个定界符以CRLF开头,所以前一个边界才具有两个后续CRLF!

A body-part may be completely empty (according the BNF). A boundary will be followed by one CRLF and then followed by either a boundary-delimiter or a end-boundary-delimiter. Only since the next delimiter starts itself with a CRLF, the preceding boundary has two subsequent CRLFs!

请注意,所有CR和LF均已明确显示.

Note, all CR and LF are shown explicitly.

示例:具有一个零件的多部分主体,两个实体标题:

Example: multipart-body with one part, two entity headers:

boundary ="1234567890"

boundary = "1234567890"

\r\n--1234567890\r\n
header1: value1\r\n
header2: value2\r\n
\r\n<data>
\r\n--0123456789--

示例:具有两部分的多部分体:

Example: multipart-body with two parts:

\r\n--1234567890\r\n
header1: value1\r\n
header2: value2\r\n
\r\n<data1>
\r\n--0123456789\r\n
header1: value1\r\n
\r\n<data2>
\r\n--0123456789--

示例:没有标题的multipart-body:

Example: multipart-body with no headers:

\r\n--1234567890\r\n
\r\n<data1>
\r\n--0123456789--

示例:主体部分为空的multipart-body:

Example: multipart-body with empty body-part:

\r\n--1234567890\r\n
\r\n--0123456789--

这篇关于NSURLRequest上传多个文件的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆