How to upload a file in custom node

Hi,

I’m trying to implement the “Upload a Document” API operation for the MFR API service (documentation: MFR OData) in my custom n8n node. I followed a similar approach from the Dropbox node, but I’m encountering errors.

You can find my current implementation here: mfr-field-service-management/nodes/Mfr/Mfr.node.ts at master · anemesMakeitfuture/mfr-field-service-management · GitHub, specifically in the uploadDocument operation.

The corresponding document description is here: mfr-field-service-management/nodes/Mfr/descriptions/DocumentDescription.ts at master · anemesMakeitfuture/mfr-field-service-management · GitHub.

Could you help me replicate the two subsequent requests from the documentation for my custom node?

Thanks,
Alex

Information on your n8n setup

  • n8n version: 1.89.2
  • Database (default: SQLite): none
  • n8n EXECUTIONS_PROCESS setting (default: own, main): own
  • Running n8n via (Docker, npm, n8n cloud, desktop app): pnpm
  • Operating system: MAC

Okay, Alex, here’s the short version with clear steps to solve the MFR API “Upload a Document” issue:

Problem: Your custom n8n node’s uploadDocument operation isn’t correctly replicating the MFR API’s likely two-step upload process.

Solution Steps:

  1. Modify uploadDocument in Mfr.node.ts to perform two API requests sequentially:
  • Request 1 (Initiate): Send metadata (filename, size, etc.) to the MFR API’s document creation/initiation endpoint. Get the upload URL or document ID from the response.
  • Request 2 (Upload): Send the binary file content (from your input’s binary data) to the upload URL obtained in the first step. Set the correct Content-Type header.
  1. Use $request() within your uploadDocument operation for both API calls.
  2. Carefully consult the MFR OData documentation for the exact endpoints, HTTP methods (likely POST for initiation, PUT or POST for upload), required headers, request body structure, and response formats for both steps.
  3. Ensure you’re sending the binary data in the second request’s body (likely as a Buffer).
  4. Handle errors for both API requests.
  5. Return relevant information (like the document ID) in your node’s output after a successful upload.

Hi @Shriket_Panchal

Thanks for responding. I understand there are 2 subsequent requests needed to upload a file to MFR, I am trying now to replicate the 1st one in n8n. Here is my code:

let bodyUploadDocument: Buffer;


let filename = 'file';
let mimeType = 'application/octet-stream';

if (this.getNodeParameter('binaryData', i)) {
	const binaryPropertyName = this.getNodeParameter('binaryPropertyName', i);
	this.helpers.assertBinaryData(i, binaryPropertyName);

	const fileData = items[i].binary?.[binaryPropertyName];

	bodyUploadDocument = await this.helpers.getBinaryDataBuffer(i, binaryPropertyName);

	if (fileData?.fileName) {
		filename = fileData.fileName;
	}
	if (fileData?.mimeType) {
		mimeType = fileData.mimeType;
	}
} else {
	bodyUploadDocument = Buffer.from(this.getNodeParameter('fileContent', i) as string, 'utf8');
	filename = 'file.txt';
	mimeType = 'text/plain';
}

const form = new FormData();
form.append('file', bodyUploadDocument, {
	filename,
	contentType: mimeType,
});
form.append('options', JSON.stringify({ filename }));


		const endpoint = `https://portal.mobilefieldreport.com/mfr/Document/UploadAndCreate`;
		const options = {
			method: 'POST',
			body: form,
      headers: form.getHeaders(),
			uri: endpoint,
			json: false,

		} satisfies IRequestOptions;

		console.log(options)


		const firstRequestResponse = await this.helpers.requestWithAuthentication.call(
			this,
			'mfrApi',
			options,
	);

	console.log(firstRequestResponse)

the request’s options look like this:

{
  method: 'POST',
  body: FormData {
    _overheadLength: 272,
    _valueLength: 13288,
    _valuesToMeasure: [],
    writable: false,
    readable: true,
    dataSize: 0,
    maxDataSize: 2097152,
    pauseStreams: true,
    _released: false,
    _streams: [
      '----------------------------799393174586832991107736\r\n' +
        'Content-Disposition: form-data; name="file"; filename="dummy.pdf"\r\n' +
        'Content-Type: application/pdf; qs=0.001\r\n' +
        '\r\n',
      [Buffer [Uint8Array]],
      [Function: bound ],
      '----------------------------799393174586832991107736\r\n' +
        'Content-Disposition: form-data; name="options"\r\n' +
        '\r\n',
      '{"filename":"dummy.pdf"}',
      [Function: bound ]
    ],
    _currentStream: null,
    _insideLoop: false,
    _pendingNext: false,
    _boundary: '--------------------------799393174586832991107736'
  },
  headers: {
    'content-type': 'multipart/form-data; boundary=--------------------------799393174586832991107736'
  },
  uri: 'https://portal.mobilefieldreport.com/mfr/Document/UploadAndCreate',
  json: false
}

However, I get this error: Cannot read properties of null (reading ‘name’).

Can you help me understand why I can’t replicate the 1st MFR request in n8n?

Thank you

@Shriket_Panchal Just wanted to see if you’ve had a chance to look at my question from five days ago.
Let me know if you need anything else from my side. Thanks!