3

GET /services/data/v47.0/sobjects/ContentVersion/0000v00000MFIVgAAP/VersionData from this request I will get binary file content, but how can I use this content to recreate the file properly (using request to POST /services/data/v47.0/sobjects/ContentVersion)?

I uploaded .docx through the UI and fetch its content. Then I uploded that content using the request:

Endpoint

/services/data/v47.0/sobjects/ContentVersion

Headers

Content-Type: multipart/form-data; boundary=boundary_string

Body

--boundary_string 
Content-Disposition: form-data; name="entity_content"; 
Content-type: application/json

{"PathOnClient":"MyFile.docx"}

--boundary_string 
Content-Type: application/octet-stream 
Content-Disposition: form-data; name="VersionData"; filename="MyFile.docx"

Binary data from the request to GET /services/data/v47.0/sobjects/ContentVersion/0000v00000MFIVgAAP/VersionData.

--boundary_string--

The request above is executed with a success status code, and the file was created successfully, but when I downloaded this file from UI, it became damaged :( There may be something in the request body that I missed (but I don’t know what exactly is wrong), so the file creates damaged. Can someone please provide me with a solution to this problem?

8
  • I'm hitting the same issue here, I've gotten this far but the file can't be opened, even though it's non-empty and it has binary data in it. Did you find a solution to this? Comparing my download to the original file, the file downloaded from salesforce is almost twice as big Commented Oct 20, 2021 at 19:28
  • yeah, It was the problem in a body. Using my own application and transferring data in proper format (binary format) everything works fine. Commented Oct 21, 2021 at 9:31
  • And you're sending binary data, not base64 encoded data? I'm trying to post the data to /ContentVersion, where the body is the binary data of a PNG file. The binary data looks fine, but when I upload to salesforce and download, the file is corrupt and slightly smaller than the original, which makes me wonder if salesforce is expecting base64 data here Commented Oct 21, 2021 at 17:15
  • it is exactly binary data Commented Oct 22, 2021 at 10:35
  • 1
    Precisely! How do I put binary data into a text multipart document with text boundaries? I notice when I try base64 I get precisely base64 back instead of my PDF. Commented Nov 12, 2021 at 3:50

1 Answer 1

0

I had similar issue when I was uploading a file from a Salesforce Guest Site and the below code worked for me.

LWC - HTML Code:

<label class="form-label" for="fileUpload">Please upload your invoice</label>
<lightning-input type="file" class="form-label" variant="label-hidden" accept=".png, .jpg, .jpeg, .pdf" onchange={openfileUpload}>
</lightning-input>
<p class="form-label"
   style="font-size: 11px;">Note: Maximum file size: 10MB. Accepted formats: .png, .jpg, .jpeg, .pdf
</p>
<template if:true={uploadedFileInfo}>
    <p class="form-label" style="color: darkblue;">{uploadedFileInfo.fileName}</p>
</template>

LWC - JS Code:

import createUploadedFile from '@salesforce/apex/YourApexClass.createUploadedFile';

@track uploadedFileInfo;

// Reading the uploaded file
openfileUpload(event) {
    const uploadedFile = event.target.files[0];
    let fileSize = uploadedFile.size;
    let fileType = uploadedFile.type;
    if(fileSize > 11004402){
        alert('Please reduce the file size');
    }
    else{
        var reader = new FileReader();
        reader.onload = () => {
            var base64 = reader.result.split(',')[1]; // This is file content
            this.uploadedFileInfo = {
                'fileName': uploadedFile.name,
                'base64': base64,
                'fileType'  : uploadedFile.type
            }
            console.log(this.uploadedFileInfo)
        }
        reader.readAsDataURL(uploadedFile)
    }
}

// Calling Apex method to create file
handleSubmit(event){
    let paramsToApex = {
        // Any other field values to be sent to server
        parentID    : 00QKN012345TCFU2A4,
        fileName    : (this.uploadedFileInfo != null && this.uploadedFileInfo.fileName != null) ? this.uploadedFileInfo.fileName : '#NO#FILE',
        base64Data  : (this.uploadedFileInfo != null && this.uploadedFileInfo.base64 != null) ? this.uploadedFileInfo.base64 : '#NO#FILE'
    }
    
    createUploadedFile({paramString : JSON.stringify(paramsToApex)}).then((result) =>{
        // Handle server response
    }).catch((error) =>{
        // Handle any errors
    });
}

Apex Code:

@AuraEnabled
public static String createUploadedFile(String paramString){
    Map<String, Object> paramsMap = (Map<String, Object>)JSON.deserializeUntyped(paramString);
    String parentID     = (String) paramsMap.get('parentID');
    String fileName     = (String) paramsMap.get('fileName');
    String base64Data   = (String) paramsMap.get('base64Data');
    if(!fileName.equalsIgnoreCase('#NO#FILE')){
        createContentVersion(fileName,base64Data,parentID);
    }
    return 'SUCCESS';
}


@future(callout=true)
public static void createContentVersion(String title, String versionData, Id parentId) {
    // If my org credentials are stored in Custom Settings. I recommend using Named Credentials instead
    API_Settings__c apiCredsCustSetting = API_Settings__c.getInstance('Self_Org_API_Details');
    String reasonForChange  = 'New Document';
    String endPointURL  = apiCredsCustSetting.endpoint__c; //Ex: https://abcOrg.my.salesforce.com
    endPointURL         = endPointURL+'/services/data/59.0/sobjects/ContentVersion/';

    String contentVersionBody = '{' +
            '"Title" : "' + title + '",' +
            '"VersionData" : "' + versionData + '",' +
            '"ReasonForChange" : "' + reasonForChange + '",' +
            '"PathOnClient" : "' + title + '"' +
            '}';

    HttpRequest request = new HttpRequest();
    request.setEndpoint(endPointURL);
    request.setMethod('POST');
    request.setHeader('Content-Type', 'application/json');
    request.setHeader('Authorization', 'Bearer ' + getAccessToken(apiCredsCustSetting));
    request.setBody(contentVersionBody);

    Http http=new Http();
    HttpResponse response=http.send(request);

    if (response.getStatusCode() == 201) {
        Map<String,Object>jsonResponse = (Map<String, Object>) JSON.deserializeUntyped(response.getBody());
        Boolean isSuccess = (Boolean) jsonResponse.get('success');

        if(isSuccess == true) {
            String newContentVersionId=(String) jsonResponse.get('id');

            ContentDocumentLink cdl = new ContentDocumentLink();
            cdl.ContentDocumentId = [SELECT ContentDocumentId FROM ContentVersion WHERE Id=: newContentVersionId LIMIT 1].ContentDocumentId;
            cdl.LinkedEntityId = parentId;
            cdl.ShareType = 'V';
            insert cdl;
        }
    }
    else {
        System.debug('Errored response: ' +response.getBody());
    }
}

You must log in to answer this question.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.