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);
        }
예제 #2
0
        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);
        }
예제 #3
0
        public void TestMultipartWriterGzipped()
        {
            var mp    = new MultipartWriter("foo/bar", "BOUNDARY");
            var data1 = Enumerable.Repeat((byte)'*', 100);

            mp.SetNextPartHeaders(new Dictionary <string, string> {
                { "Content-Type", "star-bellies" }
            });
            mp.AddGZippedData(data1);
            var output = mp.AllOutput();

            // Compression flags & OS type will differ depending on which platform this test is run on
            // So we need to compare for "almost" equality.  In this particular output the compression
            // flags are on byte 97 and the os type is in byte 98
            var expectedOutput = GetType().GetResourceAsStream("MultipartStars.mime").ReadAllBytes();

            Assert.AreEqual(expectedOutput.Take(96), output.Take(96));
            Assert.AreEqual(expectedOutput.Skip(98), output.Skip(98));
        }
예제 #4
0
        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();
            }
        }
예제 #5
0
        /// <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;
        }