Question

I am trying to POST an attachment to CouchDB using the HttpWebRequest. However, when I attempt "response = (HttpWebResponse)httpWebRequest.GetResponse();" I receive a WebException with the message "The underlying connection was closed: A connection that was expected to be kept alive was closed by the server."

I have found some articles stating that setting the keepalive to false and httpversion to 1.0 resolves the situation. I am finding that it does not yeilding the exact same error, plus I do not want to take that approach as I do not want to use the 1.0 version due to how it handles the connection.

Any suggestions or ideas are welcome. I'll try them all until one works!

public ServerResponse PostAttachment(Server server, Database db, Attachment attachment)
    {
        Stream dataStream;
        HttpWebResponse response = null;
        StreamReader sr = null;
        byte[] buffer;
        string json;
        string boundary = "----------------------------" + DateTime.Now.Ticks.ToString("x");
        string headerTemplate = "Content-Disposition: form-data; name=\"_attachments\"; filename=\"" + attachment.Filename + "\"\r\n Content-Type: application/octet-stream\r\n\r\n";
        byte[] headerbytes = System.Text.Encoding.UTF8.GetBytes(headerTemplate);
        byte[] boundarybytes = System.Text.Encoding.ASCII.GetBytes("\r\n--" + boundary + "\r\n");


        HttpWebRequest httpWebRequest = (HttpWebRequest)WebRequest.Create("http://" + server.Host + ":" + 
            server.Port.ToString() + "/" + db.Name + "/" + attachment.Document.Id);
        httpWebRequest.ContentType = "multipart/form-data; boundary=" + boundary;
        httpWebRequest.Method = "POST";
        httpWebRequest.KeepAlive = true;
        httpWebRequest.ContentLength = attachment.Stream.Length + headerbytes.Length + boundarybytes.Length;

        if (!string.IsNullOrEmpty(server.EncodedCredentials))
            httpWebRequest.Headers.Add("Authorization", server.EncodedCredentials);

        if (!attachment.Stream.CanRead)
            throw new System.NotSupportedException("The stream cannot be read.");

        // Get the request stream
        try
        {
            dataStream = httpWebRequest.GetRequestStream();
        }
        catch (Exception e)
        {
            throw new WebException("Failed to get the request stream.", e);
        }


        buffer = new byte[server.BufferSize];
        int bytesRead;

        dataStream.Write(headerbytes,0,headerbytes.Length); 

        attachment.Stream.Position = 0;
        while ((bytesRead = attachment.Stream.Read(buffer, 0, buffer.Length)) > 0)
        {
            dataStream.Write(buffer, 0, bytesRead);
        }

        dataStream.Write(boundarybytes, 0, boundarybytes.Length);
        dataStream.Close();

        // send the request and get the response
        try
        {
            response = (HttpWebResponse)httpWebRequest.GetResponse();
        }
        catch (Exception e)
        {
            throw new WebException("Invalid response received from server.", e);
        }

        // get the server's response json
        try
        {
            dataStream = response.GetResponseStream();
            sr = new StreamReader(dataStream);
            json = sr.ReadToEnd();
        }
        catch (Exception e)
        {
            throw new WebException("Failed to access the response stream.", e);
        }

        // close up all our streams and response
        sr.Close();
        dataStream.Close();
        response.Close();

        // Deserialize the server response
        return ConvertTo.JsonToServerResponse(json);
    }
Was it helpful?

Solution

After a considerable amount of research on the topic, I have decided to use PUT. While Futon uses the POST method, it is undocumented. For anyone reading this in the future, use the PUT method, it will make your life much easier.

Licensed under: CC-BY-SA with attribution
Not affiliated with StackOverflow
scroll top