Wywołanie API z klienta działa, a takie samo z Node.js już nie

0

Cześć.
Mam funkcję axios na froncie React, która wywołuje API:

export async function detect(imageDataUrl) {
	axios
		.post(url, dataURItoBlob(imageDataUrl), {
			timeout: 50000,
			headers: {
				'Ocp-Apim-Subscription-Key': subscriptionKey,
				'Content-Type': 'application/octet-stream',
			},
			params: {
				overload: 'stream',
				returnFaceId: false,
				returnFaceLandmarks: false,
				returnFaceAttributes: faceAttributes,
				detectionModel: detectionModel,
			},
		})
		.then((res) => {
			console.log(res);
		});
}

, gdzie dataURItoBlob wygląda tak:

function dataURItoBlob(dataURI) {
	var byteString = atob(dataURI.split(',')[1]);
	var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];

	var ab = new ArrayBuffer(byteString.length);
	var ia = new Uint8Array(ab);
	for (var i = 0; i < byteString.length; i++) {
		ia[i] = byteString.charCodeAt(i);
	}
	return new Blob([ab], {type: mimeString});
}

i wszystko fajnie działa i odpowiedź jest taka, jaką oczekuję.

Jednak kiedy przeniosę operację do Node.js w trosce o bezpieczeństwo o mój klucz API już tak kolorowo nie jest. Z frontu wysyłam POST do backendu Node.js:

axios.post(
	`http://localhost:3001/detect`,
	{imageDataUrl: imageDataUrl},
	{
		headers: {'Content-Type': 'application/json'},
	}
);

po czym odbieram wysłane dane i wysyłam POST to domyślnego API z tymi danymi:

app.post('/detect', async (req, res) => {
	const imageDataUrl = req.body.imageDataUrl;
	const imageBlob = dataURItoBlob(imageDataUrl);

	axios
		.post(url, imageBlob, {
			timeout: 50000,
			headers: {
				'Ocp-Apim-Subscription-Key': subscriptionKey,
				'Content-Type': 'application/octet-stream',
			},
			params: {
				overload: 'stream',
				returnFaceId: false,
				returnFaceLandmarks: false,
				returnFaceAttributes: faceAttributes,
				detectionModel: detectionModel,
			},
		})
		.then((res) => {
			console.log(res);
		});
});

jednak API zwraca mi błąd Decoding error, image format unsupported.. Możliwe, że problem występuje przez nieco inną implementację funkcji dataURItoBlob, bo w Node.js, aby stworzyć Blob trzeba to zaimportować.

const {Blob} = require('node:buffer');

exports.dataURItoBlob = function dataURItoBlob(dataURI) {
	var byteString = atob(dataURI.split(',')[1]);
	var mimeString = dataURI.split(',')[0].split(':')[1].split(';')[0];

	var ab = new ArrayBuffer(byteString.length);
	var ia = new Uint8Array(ab);
	for (var i = 0; i < byteString.length; i++) {
		ia[i] = byteString.charCodeAt(i);
	}
	return new Blob([ab], {type: mimeString});
};

Dodam jeszcze, że w obu przypadkach imageDataUrl jest stringiem w formacie Data url np. (data:image/jpeg;base64,iVBORw0KG...)

0

Porównywałeś co zwracają obie funkcje dataURItoBlob?

0
Xarviel napisał(a):

Porównywałeś co zwracają obie funkcje dataURItoBlob?

Node.js zwraca Blob { size: 38493, type: 'image/jpeg' }, a klient Blob {size: 34450, type: 'image/jpeg'}.

2

Zapewne implementacja dataURItoBlob jest błędna. Znajdź inną.

Druga opcja imageDataUrl jest źle kodowane/dekodowane w trakcie podróży między przeglądarką a serwerem, sprawdź sobie .length po obu stronach, jak jest takie samo to powinno być ok i winne jest to pierwsze

0
dzek69 napisał(a):

Zapewne implementacja dataURItoBlob jest błędna. Znajdź inną.

Druga opcja imageDataUrl jest źle kodowane/dekodowane w trakcie podróży między przeglądarką a serwerem, sprawdź sobie .length po obu stronach, jak jest takie samo to powinno być ok i winne jest to pierwsze

Długość imageDataUrl jest w obu przypadkach taka sama. Czyli wychodzi na to, że funkcje inaczej przetwarzają dane. Jednak w ogóle nie mam pomysłu dlaczego tak się dzieje. Może masz jakieś pomysły?

2

Znalazłem rozwiązanie. Okazało się, że Blob w ogóle nie jest mi potrzebny. Jedyne co musiałem zrobić to było przekonwertowanie Data URL na Buffer:

Buffer.from(imageDataUrl.split(',')[1], 'base64')

1 użytkowników online, w tym zalogowanych: 0, gości: 1