|
1 // Copyright 2009 Google Inc. All Rights Reserved. |
|
2 |
|
3 /** |
|
4 * A multipart form data construction class for XHR. |
|
5 * @see http://www.w3.org/Protocols/rfc1341/7_2_Multipart.html |
|
6 * @constructor |
|
7 */ |
|
8 var MultipartFormData = function() { |
|
9 /** |
|
10 * @type {Array} |
|
11 */ |
|
12 this.headers = []; |
|
13 |
|
14 /** |
|
15 * @type {Array} |
|
16 */ |
|
17 this.parts = []; |
|
18 |
|
19 /** |
|
20 * A random string for the boundary. |
|
21 * @type {string} |
|
22 */ |
|
23 this.boundary = MultipartFormData.getRandomBoundary(); |
|
24 }; |
|
25 |
|
26 |
|
27 /** |
|
28 * @type {string} |
|
29 */ |
|
30 MultipartFormData.CRLF = '\r\n'; |
|
31 |
|
32 |
|
33 /** |
|
34 * @type {string} |
|
35 * @private |
|
36 */ |
|
37 MultipartFormData.TEN_CHARS_ = |
|
38 |
|
39 |
|
40 /** |
|
41 * Generates a random number and some random characters from it. |
|
42 */ |
|
43 MultipartFormData.getRandomBoundary = function() { |
|
44 var anyTenCharacters = 'DiStRIcT10'; |
|
45 var randomNumber = Math.floor(Math.random() * 10000000); |
|
46 var nums = randomNumber.toString().split(''); |
|
47 var randomChars = ''; |
|
48 for (var i = 0, num; num = nums[i]; i++) { |
|
49 randomChars += anyTenCharacters[num]; |
|
50 } |
|
51 return randomChars + '-' + randomNumber; |
|
52 }; |
|
53 |
|
54 |
|
55 /** |
|
56 * @param {string} name The name for this header. |
|
57 * @param {string} value The value for this header. |
|
58 */ |
|
59 MultipartFormData.prototype.addHeader = function(name, value) { |
|
60 this.headers.push({ |
|
61 'name': name, |
|
62 'value': value |
|
63 }); |
|
64 }; |
|
65 |
|
66 |
|
67 /** |
|
68 * @param {?string} name The name for this part. |
|
69 * @param {string} value The value for this part. |
|
70 * @param {string} opt_contentType Content-type for this part. |
|
71 * @param {string} opt_contentDisposition Content disposition for this part. |
|
72 * @param {string} opt_filename The filename for this part |
|
73 */ |
|
74 MultipartFormData.prototype.addPart = function(name, value, opt_contentType, |
|
75 opt_contentDisposition, opt_filename) { |
|
76 var contentType = opt_contentType || null; |
|
77 var contentDisposition = opt_contentDisposition || null; |
|
78 var filename = opt_filename || null; |
|
79 this.parts.push({ |
|
80 'name': name, |
|
81 'value': value, |
|
82 'contentType': contentType, |
|
83 'contentDisposition': contentDisposition, |
|
84 'filename': filename |
|
85 }); |
|
86 }; |
|
87 |
|
88 /** |
|
89 * @return {string} The string to set as a payload. |
|
90 */ |
|
91 MultipartFormData.prototype.toString = function() { |
|
92 var lines = []; |
|
93 |
|
94 for (var i = 0, header; header = this.headers[i]; i++) { |
|
95 lines.push(header['name'] + ': ' + header['value']); |
|
96 } |
|
97 if (this.headers.length > 0) { |
|
98 lines.push(''); |
|
99 } |
|
100 |
|
101 for (var i = 0, part; part = this.parts[i]; i++) { |
|
102 lines.push('--' + this.boundary); |
|
103 |
|
104 if (part['contentDisposition']) { |
|
105 var contentDisposition = 'Content-Disposition: form-data; '; |
|
106 contentDisposition += 'name="' + part['name'] + '"'; |
|
107 if (part['filename']) { |
|
108 contentDisposition += '; filename="' + part['filename'] + '"'; |
|
109 } |
|
110 lines.push(contentDisposition); |
|
111 } |
|
112 |
|
113 if (part['contentType']) { |
|
114 lines.push('Content-Type: ' + part['contentType']); |
|
115 } |
|
116 |
|
117 lines.push(''); |
|
118 lines.push(part['value']); |
|
119 } |
|
120 |
|
121 lines.push('--' + this.boundary + '--'); |
|
122 |
|
123 return lines.join(MultipartFormData.CRLF) + MultipartFormData.CRLF; |
|
124 }; |
|
125 |