5

I have a download button in my visualforce page, on clicking which a text file(.txt format) has to be downloaded. This text file will be created dynamically with the data stored in a Text field of a custom object. Now I am struggling to achieve this simple download functionality without creating Attachments or Document Objects. Is there any possible way to download content as plain text file? Could someone please help me with this?

I have tried the below visualforce code, but it is not downloading any files.

<a href="data:text/plain;charset=utf-8;base64,{!getEncodedData}"> Download </a></apex:outputLabel>

where getEncodedData will be the text file body.

Apex code:

getEncodedData = EncodingUtil.base64Encode(Blob.valueOf(strContent));

I am trying to achieve this without creating Attachments, simply because the created file will not be reused later.

4 Answers 4

6

Try adding the download attribute to your link. You can read about this attributte on the Mozilla Developer Network. It notifies the browser to treat the url as a file download, and works with base64 data urls.

This snippet downloads a plaintext file for me.

<a href="data:text/plain;charset=utf-8;base64,{!FileContents}" download="description.txt">Download</a>

This snippet also uses the same encoding method as you do in your controller.

public String getFileContents() {
    return EncodingUtil.base64Encode(Blob.valueOf(description));
}

If clicking on the link you are currently using doesn't at least bring you to a page with the text content you are using on the page, then you may have a deeper issue you will need to identify.

Additionally, you can use <apex:outputLink>..</apex:outputLink> to generate the link. The html- prefix will pass any given attribute over to the generated html content, allowing you to access the download attribute through visualforce.

<apex:outputLink value="data:text/plain;charset=utf-8;base64,{!FileContents}" html-download="description.txt">Download.. </apex:outputLink>
8
  • Thanks a lot..!! This is exactly what I was looking for.:-) . Well the download part is fine, but empty file is getting downloaded, i could see that my JS function(which will call action fn to assign file content) on Onclick event, is called after file download. Any idea where I am getting wrong? May 4, 2016 at 14:48
  • Can you add your javascript to the question? May 4, 2016 at 15:06
  • please find more info on the above edited post May 4, 2016 at 15:18
  • Your javascript function seems to be pointing to an apex method which does not exist (action="{!fetchContent}"). Even if the function was changed to fetch(), you would be required to rerender your link in order to get the non-null value from getEncodedData. May 4, 2016 at 15:24
  • 1
    And will raise another Question.. :-).. Vote up for your helpful time...!! May 4, 2016 at 15:54
2

You can try to make visualforce page that is render as txt that display required field value

<apex:page standardController="Account" contentType="text/plain/#description.txt"> 
   <apex:outputText value="{!Account.Description}"/>
</apex:page>

Here is original answer -- https://developer.salesforce.com/forums/?id=906F000000097saIAA.

1
  • This seems to have worked for me! I'm not sure where the specs for the final /#description.txt descriptor comes from but it's working in Safari. Hopefully this will now also work for Edge, Firefox and Chrome on Windows.
    – Marty C.
    Feb 22, 2017 at 15:42
1

I resolved it using the javaScript download function, as the href usage fails to write the filecontent in this case. Here the exact flow.

Visualforce Code:

<apex:outputLabel onClick="javascript:fnDownloadContent('{!lstDet.ID}','{!lstDet.compId}');" >Download</apex:outputLabel>  
<apex:actionfunction name="actDnldContent" action="{!dnld_Content}" reRender="" oncomplete="javascript:download('{!filename}','{!getData}');">
<apex:param name="Id" value="" assignTo="{!Id}" />
<apex:param name="compId" value="" assignTo="{!CompId}"/>                                                                     
</apex:actionfunction>

JavaSript function:

function fnDownloadContent(ID, compID)
{
    actDnldContent(ID, compID);         
}  
function download(filename,text) 
{
    var element = document.createElement('a');
    element.setAttribute('href', 'data:text/plain;charset=utf-8,' + encodeURIComponent(text));
    element.setAttribute('download', filename);
    element.style.display = 'none';
    document.body.appendChild(element);
    element.click();
    document.body.removeChild(element);
}

In the above code, the 'filename' and 'getData' variables will be set on calling the Apex method 'dnld_Content' in the Apex Controller.

0

I resolved this problem ,I am using the javaScript download function with two ways

Visualforce page:

<apex:page controller="VFPageDownloaderController" action="{!downloadAutomatic}">
    <apex:outputText value="{!msg}" escape="false"></apex:outputText>
    
    <script>
  function download(s,filename,ext)
  {
    console.log(s+'Function call');
      const link = document.createElement('a');
  // create a blobURI pointing to our Blob
  link.href = 'data:application/'+ext+';base64,'+s;
  link.download = filename+'.'+ext;
  // some browser needs the anchor to be in the doc
  document.body.append(link);
  link.click();
  link.remove();
  // in case the Blob uses a lot of memory
       setTimeout(() => URL.revokeObjectURL(link.href), 20000);
  }

  </script>
 <apex:outputText value="{!downloadJS}" escape="false"></apex:outputText>
</apex:page>

Visualforce controller:

public class VFPageDownloaderController {
    
    public String msg {get;set;}
    public String downloadJS {get;set;}
    
    //created a function to make the API request
    public void downloadAutomatic(){
        
        String base64String = '';
        
        // download file as a blob from url request
       /* 
        Http http = new Http();
        HttpRequest request = new HttpRequest();
        request.setMethod('GET');
        request.setHeader('Content-Type', 'application/json');
        request.setEndpoint('request url');
       HttpResponse response = http.send(request);
        System.debug(response.getBodyAsBlob());
        Blob b = response.getBodyAsBlob();
        base64String = EncodingUtil.base64Encode(b); */
        
        // download file from ContentVersion
        ContentVersion c = [SELECT Id, VersionData, FileExtension, Title FROM ContentVersion limit 1];
        base64String = EncodingUtil.base64Encode(c.VersionData);
        String fileName = 'abc'; 
        if (base64String == '') {
            msg = 'file Not Found';
        }else {
              downloadJS ='<script> download("'+base64String+'","'+fileName+'","'+c.FileExtension+'"); </script>';
        }     
   } 
}

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.