You can with the ConnectAPI...that lets you create multiple message segments and upload an attachment in one post.
The code below creates a simple blob as an example, but you can use any content. I would also check out this git repo for easier segment creation
String s = 'Test my Attachment';
Blob b = blob.valueof(s);
//ConnectApi.BinaryInput(blob, contentType, filename)
ConnectApi.BinaryInput bi = new ConnectApi.BinaryInput(b, 'txt', 'testfile1.txt');
ConnectApi.MessageBodyInput messageInput = new ConnectApi.MessageBodyInput();
messageInput.messageSegments = new List<ConnectApi.MessageSegmentInput>();
ConnectApi.TextSegmentInput textSegment = new ConnectApi.TextSegmentInput();
textSegment.text = 'Enter post text here' + '\n';
messageInput.messageSegments.add(textSegment);
ConnectApi.LinkSegmentInput linkSegment = new ConnectApi.LinkSegmentInput();
linkSegment.url = 'http://www.someurl.com';
messageInput.messageSegments.add(linkSegment);
textSegment = new ConnectApi.TextSegmentInput();
textSegment.text = '\n' + 'Enter some more post text here';
messageInput.messageSegments.add(textSegment);
ConnectApi.NewFileAttachmentInput cai = new ConnectApi.NewFileAttachmentInput();
cai.title = 'My Chatter Text File';
//Create new Feed Item Input and then post to Feed in Target Object
ConnectApi.FeedItemInput input = new ConnectApi.FeedItemInput();
input.body = messageInput;
input.attachment = cai;
input.visibility = ConnectApi.FeedItemVisibilityType.InternalUsers;
//The third param is the Record Id of the object you want to post to
//The fifth is the binary input that adds the attachment
ConnectApi.FeedItem fi = ConnectApi.ChatterFeeds.postFeedItem(null, ConnectApi.FeedType.Record, 'a00w000000V32nN', input, bi);