3

Im trying to build a visualforce page to render as an attachment. It seems doable but im getting lost in the content encoding issues.. here is what i have so far

Visualforce Page:

<apex:page showHeader="false" sidebar="false" controller="AttachmentBodyController" 
           contentType="{!attachment.ContentType}#{!attachment.Name}">
{!body}
</apex:page>

Controller:

public with sharing class AttachmentBodyController {

    public String body {get; set;}
    public Attachment attachment {get; set;}
    public AttachmentBodyController() {
        String Id  = ApexPages.currentPage().getParameters().get('id');
        attachment =  [SELECT Id, Name, Body, ContentType FROM Attachment WHERE Id = :Id];
        body = EncodingUtil.base64Encode(attachment.body);
    }
}

It serves the file up and it downloads with the correct name but the encoding on the file is wrong?

  • What kind of attachment are you expecting? text/html? And to be clear, you are trying to render an attachment within a VF page and not the other way around, right? – joshbirk Sep 10 '14 at 18:00
  • my hope is that it just renders as whatever filetype the attachment is, in that if its a doc it renders as a doc, if its a jpg it renders as a jpg. – Keith Mancuso Sep 10 '14 at 22:06
  • I should mention the reason im trying to do this is cause salesforce attachments are served from a different domain name. So im tying to build a service that would serve them directly from salesforce.com/apex/whatever – Keith Mancuso Sep 10 '14 at 22:07
  • In that flow shouldn't it be a decode then? – joshbirk Sep 10 '14 at 22:26
  • Hmm maybe but how do I output raw blob content? – Keith Mancuso Sep 11 '14 at 2:14
5

You have two challenges ahead of you. One is easy, one is impossible. Let's start with the easy one.

Extra Whitespace?

Any whitespace that doesn't separate attributes will end up in the output stream, except for whitespace that separates two "apex" elements. To get rid of the extra whitespace, you have to scrunch your code together:

<apex:page ...>{!attachment.body}</apex:page>

Corrupted Data?

Visualforce emits text, not binary data. As such, the output result ends up running through a UTF-8 parser. UTF-8 disallows certain combinations of bits, such as 0xFF 0xFF. Basically, when 0x80 is set in a byte, the remainder of the 0x7F bits tell the UTF-8 stream how many more bytes to read, and each byte after must start with 0x80 with 0x40 bit set to zero, or the entire multibyte entity is also invalid.

Also, each number must be represented in the smallest space possible, or it's also invalid: 0xC0 0x01 isn't a valid UTF-8 entity. What that means is that certain types of binary data just won't work. JPEG, PNG, GIF, ZIP, etc all use binary markers, and then blocks of 8-bit data that most likely won't conform to UTF-8 patterns (most likely 100%).

So, given that we can't emit raw binary data, that means that we'd have to set the Transfer-Encoding header to base64, and emit the binary data as base64. Unfortunately, there's no way to do this, either, which leaves no viable alternatives as of yet.

  • Hi all, Do we have alternative solution for this I am trying same ?? I am getting binary response and I wan't to render it on VF page – Salesforce Learner Jan 23 '17 at 13:57
  • @SalesforceLearner There's ways to get binary data, but Visualforce isn't one of them. Perhaps a \@RestResource, or you could save the file as an Attachment, Document, ContentVersion, or something else and have the user download it via a link? – sfdcfox Jan 23 '17 at 14:45
  • Hi sfdcfox you are great help always.I am marking your answer as useful.But in my case storing as Attachment, Document, ContentVersion will not work.I have DMS(Thirdparty) where I have stored attachments.I have custom object, using custom button and webservice callout I am requesting and receiving binary response from third party....My solution approach is when user clicks on button it redirects to vf page and also requests to DMS and the response received will be shown on VF page. Is is it feasible approach or not?? – Salesforce Learner Jan 23 '17 at 14:54
  • @SalesforceLearner Visualforce is not the correct medium for binary data. Consider using a RestResource instead. You can return whatever type of data you want to. You'd just make a link to something like /services/apexrest/ResourceClass?id=ABCD; you can then make your callout in the class and return it back to the client. – sfdcfox Jan 23 '17 at 15:01
  • I wan't to display pdf from DMS(client side), here I will have to make link using restresource will not work I guess.Please suggest. – Salesforce Learner Jan 24 '17 at 4:06

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.