Google Drive API multipart upload file appears to be corrupted - salesforce

public with sharing class uploadFileToGdrive {
public static void fileUploadHandler(List<ContentVersion> cvFileList) {
for (ContentVersion cvFile : cvFileList) {
system.debug('Loop');
// Get the content of the document
ContentVersion contentVersion = [SELECT Title, VersionData, FileType FROM ContentVersion WHERE ContentDocumentId = :cvFile.contentDocumentId ORDER BY CreatedDate DESC LIMIT 1];
Blob fileBody = contentVersion.VersionData;
String fileName = contentVersion.Title;
String fileType = contentVersion.FileType;
String boundary = '-------'+contentVersion.Id;
String header = 'Content-Type: multipart/related; boundary="' + boundary + '"\n' +
'Authorization: Bearer ' + [SELECT Access_Token__c FROM gDriveTokens__c][0].Access_Token__c + '\n' +
'Content-Length: ' + String.valueOf(fileBody.size()) + '\n' +
'\n';
String body = '--' + boundary + '\n' +
'Content-Type: application/json; charset=UTF-8\n' +
'\n' +
'{"name": "' + fileName + '"}\n' +
'--' + boundary + '\n' +
'Content-Type: '+MIMEHelper.getMIMEType(fileType)+'\n' +
'\n';
String requestBody = header + body + EncodingUtil.base64Encode(fileBody) + '\n--' + boundary + '--';
uploadFileToGdrive.uploadFileCallout(requestBody, boundary);
}
}
#future(callout=true)
public static void uploadFileCallout(String requestBody, String boundary) {
system.debug('Callout');
HttpRequest req = new HttpRequest();
req.setMethod('POST');
req.setEndpoint('https://www.googleapis.com/upload/drive/v3/files?uploadType=multipart');
req.setHeader('Content-Type', 'multipart/related; boundary="' + boundary + '"');
req.setheader('Authorization','Bearer '+[SELECT Access_Token__c FROM gDriveTokens__c][0].Access_Token__c);
req.setBody(requestBody);
// Send the request
Http http = new Http();
HttpResponse res = http.send(req);
system.debug(res.getBody());
}
}
I was trying to upload a file from my salesforce system to my google drive using google drive api. The files are uploading. But when I download or try to open them, it shows this message.
Drive File Error

Related

Spring boot - I want to write a POST endpoint to consume multipart/form-data WITHOUT any file uplload, I need to post json data as key-value pair pair

I want to do something like this -
#ApiOperation("Solve for tasks in JSON file")
#PostMapping(value = "/tasks/file",
consumes = {MediaType.MULTIPART_FORM_DATA_VALUE},
produces = {MediaType.APPLICATION_JSON_VALUE})
public ResponseEntity<Plan> solveTest(#RequestBody(value = "file") InputStream filrInputStream) {}
I tried adding jersey multipart dependency in my spring boot app and tried my api method signature as below, but when I try posting my json string I get input stream as empty-
<dependency>
<groupId>org.glassfish.jersey.media</groupId>
<artifactId>jersey-media-multipart</artifactId>
</dependency>
#ApiImplicitParams({
#ApiImplicitParam(
name = "file",
dataType = "java.io.InputStream",
examples = #io.swagger.annotations.Example(
value = {
#ExampleProperty(value = "[\r\n"
+ " {\r\n"
+ " \"duration\": 0,\r\n"
+ " \"xxxxxxTG\": \"string\",\r\n"
+ " \"sequence\": 0,\r\n"
+ " \"xxxxxx\": \"string\",\r\n"
+ " \"taskId\": \"string\",\r\n"
+ " \"taskType\": \"string\",\r\n"
+ " \"xcoordinate\": 0,\r\n"
+ " \"ycoordinate\": 0\r\n"
+ " }\r\n"
+ "]", mediaType = "multipart/form-data")
}))
})
#PostMapping(value = "/tasks/file",
consumes = {MediaType.MULTIPART_FORM_DATA_VALUE},
produces = {MediaType.APPLICATION_JSON_VALUE}
)
public ResponseEntity<Plan> solveTest1(#FormDataParam("file") InputStream file, #FormDataParam("file") FormDataContentDisposition fileMetaData)

suitescript: POST an image form the cabinet multipart/form-data

I am trying to post an image form the cabinet to an API
the API is rejected call with Content-Type": "multipart/form-data:
{
httpCode: "405",
httpMessage: "Method Not Allowed",
message: "PUT, POST require an input body.",
errorClass: "Exception"
}
the API is rejected call without Content-Type": "multipart/form-data:
{
httpCode: "400",
httpMessage: "Bad Request",
message: "JSON Input was invalid. Error Message: Syntax error",
errorClass: "InvalidArgumentException"
}
the current code is:
function ItemImageCreation(){
var itemId = 4;
var payload;
var StringUrl = "https://someURL";
var boundary = '--' + uuidv4();
var files = file.load(1056); // getting the file
var fileContents = files.getContents(); // getting the content
var decodedStr = fromBaseUTF(fileContents); // conversion to Base64
var form_data = "{\"description\": \"Test Image\",\n\"ordering\": 1\n}";
// add the data field
payload = "\n" + boundary + "\n"
+ 'Content-Disposition: form-data; name=\"data\"\n\n'
+ form_data + "\n"
+ boundary + "\n"
+ 'Content-Disposition: form-data; name=\"image\"\n'
+ 'Content-Type: image/jpeg\n\n'
+ decodedStr + "\n"
+ boundary + "--\n\n";
log.debug("payload", payload);
var Header = {"Authorization": "Bearer " + token,
"Content-Type": "multipart/form-data; boundary=" + boundary
};
try {
var response = https.post({
url: StringUrl,
body: payload,
headers: Header
});
var newSFID = JSON.parse(response.body);
log.debug("Item Image creation", newSFID);
} catch (e) {
log.error({ title: 'Failed to submit file', details: (e.message || e.toString()) + (e.getStackTrace ? (' \n \n' + e.getStackTrace().join(' \n')) : '') });
log.error('ERROR Item Image Creation', JSON.stringify(e));
}
}
using postman, the image is correctly sent:
I am using a scheduled script, do you see what is wrong or is there a way to know what is send by netsuite?
There is an answer here that covers this: In NetSuite with SuiteScript 2.0 unable to send a file with HTTP POST request with a content-type multipart/form-data
what you missing is the Content-Transfer-Encoding header and you should be getting the content as Base64 so you shouldn't need to convert from UTF16 ( I could be wrong on that but I've never needed to)

Mule - Salesforce connector - Retrieve job failed results bulk v2 - not returning failed data

I am querying Salesforce Bulk api failed results in Mule. But it doesn't fetch the data. It jus shows the record id and error message. But if i check in workbench, it shows the id, error, datacolumns(a,b,c)
How to get those details..Is there any other way to get the bulk api v2 failed results in Mule
doing simple Transformation before logging
%dw 2.0
output application/json
---
payload
Debug Log :
On workbench, I get the actual data.
please share your thoughts why i don't see those data
#RestResource(urlMapping='/bulkapi/failures')
global without sharing class RestGetBulkAPIResults
{
#HttpGet
global static void getFailedRecords()
{
RestRequest req = RestContext.request;
RestResponse res = RestContext.response;
res.addHeader('Content-Type', 'application/json');
Http http = new Http();
HttpRequest httpReq = new HttpRequest();
HttpResponse httpRes = new HttpResponse();
httpReq.setMethod('GET');
httpReq.setHeader('Authorization', 'Bearer ' + UserInfo.getSessionId());
string path = '/services/data/v48.0/jobs/ingest/7502i000001fJG9AAM/failedResults/';
httpReq.setEndpoint(URL.getSalesforceBaseUrl().toExternalForm()+ path);
httpRes = http.send(httpReq);
string op = httpRes.getBody();
string[] rowList = op.split('\n');
string[] headers = rowList[0].split(',');
integer columnsCount = headers.size();
integer dataRowsCount = rowList.size();
string fullFormattedData = '[';
for(integer rowIndex =1; rowIndex < dataRowsCount; rowIndex++)
{
string[] rowData = rowList[rowIndex].split(',');
string rowJsonData ='{';
for(integer columnIndex=0; columnIndex < columnsCount; columnIndex++)
{
rowJsonData += headers[columnIndex] + ':' + rowData[columnIndex] + ',';
}
rowJsonData = rowJsonData.removeEnd(',');
rowJsonData += '}';
fullFormattedData += rowJsonData;
}
fullFormattedData += ']';
system.debug('resp' + httpRes.getBody());
res.responseBody = Blob.valueOf(fullFormattedData);
res.statusCode = 200;
}
}

Httprequest error. Help to make the correct request

I have example request:
curl https://upload.box.com/api/2.0/files/content \
-H "Authorization: Bearer ACCESS_TOKEN" \
-F filename=#FILE_NAME \
-F parent_id=PARENT_FOLDER_ID
My request returns an error missing_parameter","name":"parent","message":"'parent' is required".
This is my request:
String boundary = String.valueOf(DateTime.now().getTime());
String body = '------------' + boundary + '\r\n';
body +='Content-Disposition: form-data; name="FileName"; FileName="' + fileBody +'"\r\n';
body+='Content-Transfer-Encoding: base64\r\n';
if ((contentType == null) || (contentType == '')){contentType = 'application/octet-stream';}
body+='Content-Type: ' + contentType + '\r\n\r\n';
body+=EncodingUtil.base64Encode(fileBody);
body +='Content-Disposition: form-data; name="Parent"; \r\n';
body+='Content-Transfer-Encoding: base64\r\n';
if ((contentType == null) || (contentType == '')){contentType = 'application/octet-stream';}
body+='Content-Type: ' + contentType + '\r\n\r\n';
body+=0;
body+='\r\n------------' + boundary + '--';
HttpRequest req = new HttpRequest();
req.setHeader('Content-Type', 'multipart/form-data; boundary=----------' + boundary);
req.setHeader('Content-Length',String.valueof(body.length()));
req.setBody(body);
req.setHeader('Authorization', 'Bearer ' + accessToken.token__c);
req.setMethod('POST');
req.setEndpoint('https://upload.box.com/api/2.0/files/content');
Http http = new Http();
HttpResponse res = http.send(req);
It's asking for the ID of the folder you want to upload to.
try changing this line:
body +='Content-Disposition: form-data; name="Parent"; \r\n';
to:
body +='Content-Disposition: form-data; name="parent_id"; \r\n';
EDIT: though I have to ask, why are you sending the whole file body as the file name?

Cannot send a content-body with this verb-type. error while getting response when trying to Upload file in Box Storage

When i am trying to upload files in Box Storage using api provided by Box but at response time i am getting this error
public static void UploadFileRequest(string FolderID, string accesstoken)
{
string boundary = string.Format("----------------------------{0}", DateTime.Now.Ticks.ToString("x"));
string filename="C:\\Users\\Administrator\\Desktop\\Text.txt";
HttpWebRequest httpWReq = (HttpWebRequest)WebRequest.Create("https://upload.box.com/api/2.0/files/content");
ASCIIEncoding encoding = new ASCIIEncoding();
string hh = "\"filename=#\"" + filename + "\" "+";"+"";
hh += "parent_id=\"" + FolderID + "\"";
string kj = string.Format(("filename=#" + filename));
byte[] data = encoding.GetBytes(hh);
httpWReq.Headers.Add("Authorization", "Bearer " + accesstoken);
httpWReq.ContentType = "application/json";
httpWReq.ContentLength = data.Length;
using (Stream stream = httpWReq.GetRequestStream())
{
stream.Write(data, 0, data.Length);
}
HttpWebResponse response = (HttpWebResponse)httpWReq.GetResponse();
string responseString = new StreamReader(response.GetResponseStream()).ReadToEnd();
}
Without knowing the Box API, I will assume that the upload should be a POST operation, so you will need to specify the correct HTTP method on your request, before sending it:
httpWReq.Method = "POST";
The Method property defaults to "GET", and GET operations does not normally have a body..
Here is the solution , as C# accepts bytes format and then any Upload is done , i was missing that .. hope it helps
private void UploadBoxFile(string Filename)
{
HttpWebRequest req = HttpWebRequest.Create("https://upload.box.com/api/2.0/files/content") as HttpWebRequest;
req.Method = "POST";
req.Headers.Add("Authorization", "Bearer < Access Token >");
req.ContentType = "multipart/form-data; boundary=\"d174f29b-6def-47db-8519-3da38b21b398\"";
string Content = GetFormatedData(Filename);
req.ContentLength = Content.Length;
using (Stream Writer = req.GetRequestStream())
{
Writer.Write(Encoding.UTF8.GetBytes(Content), 0, Content.Length);
}
req.GetResponse();
}
private string GetFormatedData(string Filename)
{
StringBuilder build = new StringBuilder();
string Id = "d174f29b-6def-47db-8519-3da38b21b398";
build.AppendLine("--" + Id);
build.AppendLine("Content-Disposition: form-data; filename=\"hello1.txt\"; name=\"filename\"");
build.AppendLine("Content-Type: application/octet-stream");
build.AppendLine();
string FileContent = "This is a sample text";
build.AppendLine(FileContent);
build.AppendLine("--" + Id);
build.AppendLine("Content-Disposition: form-data; name=\"folder_id\"");
build.AppendLine();
build.AppendLine("0");
build.AppendLine("--" + Id + "--");
return build.ToString();
}
Thanks..

Resources