private MultipartWriter GetMultipartWriter(RevisionInternal rev, string boundary) { // Find all the attachments with "follows" instead of a body, and put 'em in a multipart stream. // It's important to scan the _attachments entries in the same order in which they will appear // in the JSON, because CouchDB expects the MIME bodies to appear in that same order var bodyStream = default(MultipartWriter); var attachments = rev.GetAttachments(); foreach (var a in attachments) { var attachment = a.Value.AsDictionary <string, object>(); if (attachment != null && attachment.GetCast <bool>("follows")) { if (bodyStream == null) { // Create the HTTP multipart stream: bodyStream = new MultipartWriter("multipart/related", boundary); bodyStream.SetNextPartHeaders(new Dictionary <string, string> { { "Content-Type", "application/json" } }); // Use canonical JSON encoder so that _attachments keys will be written in the // same order that this for loop is processing the attachments. var json = Manager.GetObjectMapper().WriteValueAsBytes(rev.GetProperties(), true); if (CanSendCompressedRequests) { bodyStream.AddGZippedData(json); } else { bodyStream.AddData(json); } } // Add attachment as another MIME part: var disposition = String.Format("attachment; filename={0}", Misc.QuoteString(a.Key)); var contentType = attachment.GetCast <string>("type"); var contentEncoding = attachment.GetCast <string>("encoding"); bodyStream.SetNextPartHeaders(new NonNullDictionary <string, string> { { "Content-Disposition", disposition }, { "Content-Type", contentType }, { "Content-Encoding", contentEncoding } }); var attachmentObj = default(AttachmentInternal); try { attachmentObj = LocalDatabase.AttachmentForDict(attachment, a.Key); } catch (CouchbaseLiteException) { return(null); } bodyStream.AddStream(attachmentObj.ContentStream, attachmentObj.Length); } } return(bodyStream); }
public void TestMultipartWriter() { const string expectedOutput = "\r\n--BOUNDARY\r\nContent-Length: 16\r\n\r\n<part the first>\r\n--BOUNDARY\r\nContent-Length: " + "10\r\nContent-Type: something\r\n\r\n<2nd part>\r\n--BOUNDARY--"; for (var bufSize = 1; bufSize < expectedOutput.Length - 1; ++bufSize) { var mp = new MultipartWriter("foo/bar", "BOUNDARY"); Assert.AreEqual("foo/bar; boundary=\"BOUNDARY\"", mp.ContentType); Assert.AreEqual("BOUNDARY", mp.Boundary); mp.AddData(Encoding.UTF8.GetBytes("<part the first>")); mp.SetNextPartHeaders(new Dictionary <string, string> { { "Content-Type", "something" } }); mp.AddData(Encoding.UTF8.GetBytes("<2nd part>")); Assert.AreEqual(expectedOutput.Length, mp.Length); var output = mp.AllOutput(); Assert.IsNotNull(output); Assert.AreEqual(expectedOutput, Encoding.UTF8.GetString(output.ToArray())); mp.Close(); } }
private static MultipartWriter MultipartWriterForRev(Database db, RevisionInternal rev, string contentType) { var writer = new MultipartWriter(contentType, null); writer.SetNextPartHeaders(new Dictionary <string, string> { { "Content-Type", "application/json" } }); writer.AddData(rev.GetBody().AsJson()); var attachments = rev.GetAttachments(); if (attachments == null) { return(writer); } foreach (var entry in attachments) { var attachment = entry.Value.AsDictionary <string, object>(); if (attachment != null && attachment.GetCast <bool>("follows", false)) { var disposition = String.Format("attachment; filename={0}", Database.Quote(entry.Key)); writer.SetNextPartHeaders(new Dictionary <string, string> { { "Content-Disposition", disposition } }); var attachObj = default(AttachmentInternal); try { attachObj = db.AttachmentForDict(attachment, entry.Key); } catch (CouchbaseLiteException) { return(null); } var fileURL = attachObj.ContentUrl; if (fileURL != null) { writer.AddFileUrl(fileURL); } else { writer.AddStream(attachObj.ContentStream); } } } return(writer); }
/// <summary> /// Creates and sets a multipart writer given the list of data to send /// </summary> /// <param name="parts">The list of data to transmit</param> /// <param name="type">The base type of the multipart writer</param> public void SetMultipartBody(IList <object> parts, string type) { var mp = new MultipartWriter(type, null); object nextPart; foreach (var part in parts) { if (!(part is IEnumerable <byte>)) { nextPart = Manager.GetObjectMapper().WriteValueAsBytes(part); mp.SetNextPartHeaders(new Dictionary <string, string> { { "Content-Type", "application/json" } }); } else { nextPart = part; } mp.AddData((IEnumerable <byte>)nextPart); } MultipartWriter = mp; }