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?

7
  • 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
    Commented Sep 10, 2014 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. Commented Sep 10, 2014 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 Commented Sep 10, 2014 at 22:07
  • In that flow shouldn't it be a decode then?
    – joshbirk
    Commented Sep 10, 2014 at 22:26
  • Hmm maybe but how do I output raw blob content? Commented Sep 11, 2014 at 2:14

1 Answer 1

6

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.

13
  • 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 Commented Jan 23, 2017 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
    Commented Jan 23, 2017 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?? Commented Jan 23, 2017 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
    Commented Jan 23, 2017 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. Commented Jan 24, 2017 at 4:06

You must log in to answer this question.

Not the answer you're looking for? Browse other questions tagged .