0

I looked at the messenger documentation at https://developers.facebook.com/docs/messenger-platform/send-messages/#file to try and figure out how to send local attachments. However, when I try it out with a httpclient I get an error saying that the message body can not be empty must provide a valid attachment or message. Below is my code

string fileType = ImageExtensions.Contains(Path.GetExtension(url).ToUpper()) ? "image" : "file";

var multipartContent = new MultipartFormDataContent();

var content = new StringContent($"{{\"attachment\":{{\"type\":\"{fileType}\", \"payload\":{{\"is_reusable\"=true}}}}");

multipartContent.Add(new StringContent($"{{\"id\":\"{long.Parse(recipient)}\"}}"), "recipient");
multipartContent.Add(new StringContent($"{{\"attachment\":{{\"type\":\"{fileType}\", \"payload\":{{\"is_reusable\"=true}}}}"), "message");

var file1 = File.ReadAllBytes(url);
var file2 = new ByteArrayContent(file1);

file2.Headers.Add("Content-Type", GetMimeType(Path.GetExtension(url)));

multipartContent.Add(file2,"filedata", Path.GetFileName(url));
request.Content = multipartContent;

The file type is image and the mime type is image/jpeg. I know the url exists as I checked File.exists

2 Answers 2

0

Welcome to Stack Overflow!

From the code sample provided it's quite hard to work out what's going wrong as it's not runnable in isolation.

That said, I'd first verify that the image you're consuming by url exists in the format you expect. If you download the .jpeg from the url can you open it on your machine? Assuming it's well structured I'd then try and work out if it's the HttpClient that's malformed - or if there's something wrong with the values you're providing to the Facebook API.

You can do this by creating a simple C# Web API project that listens for a multipart upload on a specific route. See this answer for some sample code on how to do this.

Assuming that you're able to send the .jpeg in question between a local client and a local endpoint accepting a multipart/form-data header then the issue must be with how you're using the Facebook API itself.

In your sample I don't see you using the value of the content variable anywhere. Is this intentional?

If that missing variable is a red-herring then you could try running something along the lines of (making sure to swap the values out as necessary for the ones you're having problems with):

using (var httpClient = new HttpClient())
using (var formDataContent = new MultipartFormDataContent()) 
{
    // Read the file in from a local path first to verify that the image
    // exists in the format you're expecting.
    var fileStream = File.OpenRead("/some/path/image.jpeg");
    using (var streamContent = new StreamContent(fileStream)) 
    {
        // Don't actually call `.Result` you should await this, but for ease of
        // demonstration.
        var imageContent = new ByteArrayContent(streamContent.ReadAsByteArrayAsync().Result);
        imageContent.Headers.ContentType = MediaTypeHeaderValue.Parse("multipart/form-data");

        formDataContent.Add(imageContent, "image", "your-file-name-here");
        formDataContent.Add(new StringContent ($"{{\"id\":\"{long.Parse("your-recipient-here")}\"}}"), "recipient");
        formDataContent.Add(new StringContent($"{{\"attachment\":{{\"type\":\"{"image"}\", \"payload\":{{\"is_reusable\"=true}}}}"), "message");

        // Again don't call `.Result` - await it.
        var response = httpClient.PostAsync("https://some-url-here.com", formDataContent).Result;
    }    
}

If you run the above do you still get an empty message body error?

Sign up to request clarification or add additional context in comments.

12 Comments

Ah thanks for the response. I didn't mean to never use the content variable. When I tried to create the c# web api project, I got an error saying "Unable to read data from the transport connection: An existing connection was forcibly closed by the remote host." I think that is more referring to the fact I didn't create the api properly though.
I also tried to turn the code you posted but I still get the exact same error message.
No worries. I've created a sample application that works locally for me for testing a POST of a *.jpeg file. If you clone that, and update the MockMessenger.Client project's Program.cs file to have your image request in the GetImageBytes method do you see it created as expected on disk & posted without exception? I'll have a closer read through the FB docs now - I may just be missing something obvious in your use of the API.
I get an error saying Error reading mime multiparty body part with an inner exception of Maximum request length exceeded. Is my file too big to be uploaded?
Ah! That's good to know. What is the size of the file on disk? By default IIS limits to a few MB per request. You can bump this up in the web.config file though - take a look at this answer. FYI the Facebook Send API has a hard limit of 25MB per file upload - as per this doc page.
|
0

If you stumble upon this and you're using the FacebookClient from Nuget. This is how I finally managed to upload files to the messages api using vb.net.

Dim Client = New FacebookClient(GetPageAccessToken(PageID))
Dim TmpParams As New Dictionary(Of String, Object)

TmpParams.Add("recipient", "{""id"":""RECIPIENT_ID""}")
TmpParams.Add("message", "{""attachment"":{""type"":""image"", ""payload"":{""url"":"""", ""is_reusable"":false}}}")
TmpParams.Add("messaging_type", "RESPONSE")

Dim Med As New FacebookMediaObject()
Med.FileName = YourFile.FileName
Med.ContentType = YourFile.ContentType
Med.SetValue(YourFile.InputStream.ToBytes())

TmpParams.Add(YourFile.FileName, Med)

Client.Post("me/messages", TmpParams)

Using a Dictionary(of string,object), manually add the params for recipient,message,messaging_type and the file bytes.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.