You need to sign in to do that
Don't have an account?
sukanta Anbu 7
The encoded multi-part file that I am sending through POST method is corrupted. I want to send a proper file
I am getting a file from lightning cmponent.I am using base64 in objreader in my helper.js to pass the file to the cntroller. I am doing a base64 encoding for multi-part file and the final body, I am doing a base64 decoding. However, this file is getting encoded 2 times cause of the encoding in js. Help me in decoding the file from js so I can do the encoding for multi-part.
The following is my helper.js file:
({
MAX_FILE_SIZE: 4500000, //Max file size 4.5 MB
CHUNK_SIZE: 750000, //Chunk Max size 750Kb
uploadHelper: function(component, event) {
// get the selected files using aura:id [return array of files]
var fileInput = component.find("fuploader").get("v.files");
// get the first file using array index[0]
var file = fileInput[0];
var self = this;
// check the selected file size, if select file size greter then MAX_FILE_SIZE,
// then show a alert msg to user,hide the loading spinner and return from function
if (file.size > self.MAX_FILE_SIZE) {
component.set("v.fileName", 'Alert : File size cannot exceed ' + self.MAX_FILE_SIZE + ' bytes.\n' + ' Selected file size: ' + file.size);
return;
}
// create a FileReader object
var objFileReader = new FileReader();
// set onload function of FileReader object
objFileReader.onload = $A.getCallback(function() {
var fileContent = objFileReader.result;
var base64 = 'base64,';
var dataStart = fileContent.indexOf(base64) + base64.length;
fileContent = fileContent.substring(dataStart);
// call the uploadProcess method
self.uploadProcess(component, file, fileContent);
});
objFileReader.readAsDataURL(file);
},
uploadProcess: function(component, file, fileContent) {
// set a default size or startpostiton as 0
var startPosition = 0;
// calculate the end size or endPostion using Math.min() function which is return the min. value
var endPosition = Math.min(fileContent.length, startPosition + this.CHUNK_SIZE);
// start with the initial chunk, and set the attachId(last parameter)is null in begin
this.uploadInChunk(component, file, fileContent, startPosition, endPosition, '');
},
uploadInChunk: function(component, file, fileContent, startPosition, endPosition, attachId) {
// call the apex method 'SaveFile'
var getchunk = fileContent.substring(startPosition, endPosition);
var action = component.get("c.SaveFile");
action.setParams({
recordId: component.get("v.recordId"),
fileName: file.name,
contentType: file.type,
file: fileContent
});
// set call back
action.setCallback(this, function(response) {
// store the response / Attachment Id
returnValue = response.getReturnValue();
var state = response.getState();
if (state === "SUCCESS") {
// update the start position with end postion
startPosition = endPosition;
endPosition = Math.min(fileContent.length, startPosition + this.CHUNK_SIZE);
// check if the start postion is still less then end postion
// then call again 'uploadInChunk' method ,
// else, diaply alert msg and hide the loading spinner
if (startPosition < endPosition) {
this.uploadInChunk(component, file, fileContent, startPosition, endPosition, returnValue);
} else {
alert('File has been uploaded successfully');
}
// handel the response errors
} else if (state === "INCOMPLETE") {
alert("From server: " + response.getReturnValue());
} else if (state === "ERROR") {
var errors = response.getError();
if (errors) {
if (errors[0] && errors[0].message) {
console.log("Error message: " + errors[0].message);
}
} else {
console.log("Unknown error");
}
}
});
// enqueue the action
$A.enqueueAction(action);
},
})
The following is my apex class:
public class FileUploadController {
@AuraEnabled
public static String SaveFile(String recordId, String fileName, Blob file) {
system.debug(recordId);
system.debug(fileName);
Http h = new Http();
//it should automaticaly catch the file name
// String fileName = 'sf.pdf';
String url = 'https://intelligent-sfdms.herokuapp.com/salesforce/jsonupload/'+ recordId+'/';
String separationString = '2a8b828b-ee1e-461b-87fe-ce69c0491b04';
String token = 'RGLYisTnzvEIRTCOJV7G3KUgnwNhYZXgKJJaOMQkgTq97RnDz6pmwuMqd9F9GBXy';
String header = '--'+separationString+'\r\nContent-Disposition: form-data; name="file"; filename="'+ fileName +'" \r\nContent-Type: application/octet-stream';
String footer = '--'+separationString+'--';
String headerEncoded = EncodingUtil.base64Encode(Blob.valueOf(header+'\r\n\r\n'));
while(headerEncoded.endsWith('='))
{
header+=' ';
headerEncoded = EncodingUtil.base64Encode(Blob.valueOf(header+'\r\n\r\n'));
}
String bodyEncoded = EncodingUtil.base64Encode(file);
Blob bodyBlob = null;
String last4Bytes = bodyEncoded.substring(bodyEncoded.length()-4,bodyEncoded.length());
if(last4Bytes.endsWith('==')) {
last4Bytes = last4Bytes.substring(0,2) + '0K';
bodyEncoded = bodyEncoded.substring(0,bodyEncoded.length()-4) + last4Bytes;
String footerEncoded = EncodingUtil.base64Encode(Blob.valueOf(footer));
bodyBlob = EncodingUtil.base64Decode(headerEncoded+bodyEncoded+footerEncoded);
} else if(last4Bytes.endsWith('=')) {
last4Bytes = last4Bytes.substring(0,3) + 'N';
bodyEncoded = bodyEncoded.substring(0,bodyEncoded.length()-4) + last4Bytes;
footer = '\n' + footer;
String footerEncoded = EncodingUtil.base64Encode(Blob.valueOf(footer));
bodyBlob = EncodingUtil.base64Decode(headerEncoded+bodyEncoded+footerEncoded);
} else {
// Prepend the CR LF to the footer
footer = '\r\n' + footer;
String footerEncoded = EncodingUtil.base64Encode(Blob.valueOf(footer));
bodyBlob = EncodingUtil.base64Decode(headerEncoded+bodyEncoded+footerEncoded);
}
system.debug('string ==>'+bodyBlob);
system.debug('bodyBlob: ' + bodyBlob);
HttpRequest req = new HttpRequest();
req.setHeader('Content-Type', 'multipart/form-data; boundary=' +separationString);
req.setHeader('X-CSRFToken', token);
req.setHeader('Cookie', 'sessionid=ml0as2d28qbh8du2p3299ty2oof4axcu; csrftoken=RGLYisTnzvEIRTCOJV7G3KUgnwNhYZXgKJJaOMQkgTq97RnDz6pmwuMqd9F9GBXy');
req.setHeader('Referer', 'https://intelligent-sfdms.herokuapp.com/salesforce/login/');
req.setHeader('recordId', recordId);
req.setEndpoint(url);
req.setMethod('POST');
req.setBodyAsBlob(bodyBlob);
req.setTimeout(120000);
system.debug('REQUEST: ' + req);
// Send the request, and return a response
HttpResponse res = h.send(req);
System.debug(res.getBody());
return res.getBody();
}
}
Around line 12 or 13, I have to decode the blop file that I am getting through the paraeter from UI. Please help me decoding it.
If I convert the blob file to string and then decode it, I am able to decoe it. How ever the final blob fle can only be .csv or .txt. It is not accepting any other file types like png or pdf or jpg.So I cannot convert it to string.
How can I decode the file from the js file so I can use the Multi-part encoding that I have did?
The following is my helper.js file:
({
MAX_FILE_SIZE: 4500000, //Max file size 4.5 MB
CHUNK_SIZE: 750000, //Chunk Max size 750Kb
uploadHelper: function(component, event) {
// get the selected files using aura:id [return array of files]
var fileInput = component.find("fuploader").get("v.files");
// get the first file using array index[0]
var file = fileInput[0];
var self = this;
// check the selected file size, if select file size greter then MAX_FILE_SIZE,
// then show a alert msg to user,hide the loading spinner and return from function
if (file.size > self.MAX_FILE_SIZE) {
component.set("v.fileName", 'Alert : File size cannot exceed ' + self.MAX_FILE_SIZE + ' bytes.\n' + ' Selected file size: ' + file.size);
return;
}
// create a FileReader object
var objFileReader = new FileReader();
// set onload function of FileReader object
objFileReader.onload = $A.getCallback(function() {
var fileContent = objFileReader.result;
var base64 = 'base64,';
var dataStart = fileContent.indexOf(base64) + base64.length;
fileContent = fileContent.substring(dataStart);
// call the uploadProcess method
self.uploadProcess(component, file, fileContent);
});
objFileReader.readAsDataURL(file);
},
uploadProcess: function(component, file, fileContent) {
// set a default size or startpostiton as 0
var startPosition = 0;
// calculate the end size or endPostion using Math.min() function which is return the min. value
var endPosition = Math.min(fileContent.length, startPosition + this.CHUNK_SIZE);
// start with the initial chunk, and set the attachId(last parameter)is null in begin
this.uploadInChunk(component, file, fileContent, startPosition, endPosition, '');
},
uploadInChunk: function(component, file, fileContent, startPosition, endPosition, attachId) {
// call the apex method 'SaveFile'
var getchunk = fileContent.substring(startPosition, endPosition);
var action = component.get("c.SaveFile");
action.setParams({
recordId: component.get("v.recordId"),
fileName: file.name,
contentType: file.type,
file: fileContent
});
// set call back
action.setCallback(this, function(response) {
// store the response / Attachment Id
returnValue = response.getReturnValue();
var state = response.getState();
if (state === "SUCCESS") {
// update the start position with end postion
startPosition = endPosition;
endPosition = Math.min(fileContent.length, startPosition + this.CHUNK_SIZE);
// check if the start postion is still less then end postion
// then call again 'uploadInChunk' method ,
// else, diaply alert msg and hide the loading spinner
if (startPosition < endPosition) {
this.uploadInChunk(component, file, fileContent, startPosition, endPosition, returnValue);
} else {
alert('File has been uploaded successfully');
}
// handel the response errors
} else if (state === "INCOMPLETE") {
alert("From server: " + response.getReturnValue());
} else if (state === "ERROR") {
var errors = response.getError();
if (errors) {
if (errors[0] && errors[0].message) {
console.log("Error message: " + errors[0].message);
}
} else {
console.log("Unknown error");
}
}
});
// enqueue the action
$A.enqueueAction(action);
},
})
The following is my apex class:
public class FileUploadController {
@AuraEnabled
public static String SaveFile(String recordId, String fileName, Blob file) {
system.debug(recordId);
system.debug(fileName);
Http h = new Http();
//it should automaticaly catch the file name
// String fileName = 'sf.pdf';
String url = 'https://intelligent-sfdms.herokuapp.com/salesforce/jsonupload/'+ recordId+'/';
String separationString = '2a8b828b-ee1e-461b-87fe-ce69c0491b04';
String token = 'RGLYisTnzvEIRTCOJV7G3KUgnwNhYZXgKJJaOMQkgTq97RnDz6pmwuMqd9F9GBXy';
String header = '--'+separationString+'\r\nContent-Disposition: form-data; name="file"; filename="'+ fileName +'" \r\nContent-Type: application/octet-stream';
String footer = '--'+separationString+'--';
String headerEncoded = EncodingUtil.base64Encode(Blob.valueOf(header+'\r\n\r\n'));
while(headerEncoded.endsWith('='))
{
header+=' ';
headerEncoded = EncodingUtil.base64Encode(Blob.valueOf(header+'\r\n\r\n'));
}
String bodyEncoded = EncodingUtil.base64Encode(file);
Blob bodyBlob = null;
String last4Bytes = bodyEncoded.substring(bodyEncoded.length()-4,bodyEncoded.length());
if(last4Bytes.endsWith('==')) {
last4Bytes = last4Bytes.substring(0,2) + '0K';
bodyEncoded = bodyEncoded.substring(0,bodyEncoded.length()-4) + last4Bytes;
String footerEncoded = EncodingUtil.base64Encode(Blob.valueOf(footer));
bodyBlob = EncodingUtil.base64Decode(headerEncoded+bodyEncoded+footerEncoded);
} else if(last4Bytes.endsWith('=')) {
last4Bytes = last4Bytes.substring(0,3) + 'N';
bodyEncoded = bodyEncoded.substring(0,bodyEncoded.length()-4) + last4Bytes;
footer = '\n' + footer;
String footerEncoded = EncodingUtil.base64Encode(Blob.valueOf(footer));
bodyBlob = EncodingUtil.base64Decode(headerEncoded+bodyEncoded+footerEncoded);
} else {
// Prepend the CR LF to the footer
footer = '\r\n' + footer;
String footerEncoded = EncodingUtil.base64Encode(Blob.valueOf(footer));
bodyBlob = EncodingUtil.base64Decode(headerEncoded+bodyEncoded+footerEncoded);
}
system.debug('string ==>'+bodyBlob);
system.debug('bodyBlob: ' + bodyBlob);
HttpRequest req = new HttpRequest();
req.setHeader('Content-Type', 'multipart/form-data; boundary=' +separationString);
req.setHeader('X-CSRFToken', token);
req.setHeader('Cookie', 'sessionid=ml0as2d28qbh8du2p3299ty2oof4axcu; csrftoken=RGLYisTnzvEIRTCOJV7G3KUgnwNhYZXgKJJaOMQkgTq97RnDz6pmwuMqd9F9GBXy');
req.setHeader('Referer', 'https://intelligent-sfdms.herokuapp.com/salesforce/login/');
req.setHeader('recordId', recordId);
req.setEndpoint(url);
req.setMethod('POST');
req.setBodyAsBlob(bodyBlob);
req.setTimeout(120000);
system.debug('REQUEST: ' + req);
// Send the request, and return a response
HttpResponse res = h.send(req);
System.debug(res.getBody());
return res.getBody();
}
}
Around line 12 or 13, I have to decode the blop file that I am getting through the paraeter from UI. Please help me decoding it.
If I convert the blob file to string and then decode it, I am able to decoe it. How ever the final blob fle can only be .csv or .txt. It is not accepting any other file types like png or pdf or jpg.So I cannot convert it to string.
How can I decode the file from the js file so I can use the Multi-part encoding that I have did?
Best Answer chosen by sukanta Anbu 7
sukanta Anbu 7
The base64 decoding was done on the end point url side. Once the decoding was done on the end point side, the situation was solved.