I am trying to send a blob (will be a file from another API in future) as the response for a api call in next13 api routes. My handler goes like:
export default async function handler(req, res) {
const endpoint = `${process.env.UI_ENGINE}/docs/${req.query.id}/download-doc`;
const response = await fetch(endpoint, {
headers: { Authorization: `${req.headers.authorization}` },
});
const blob = await response.blob();
console.log("»»»»»» [DEBUG : blob ] -- :", blob); // Blob { size: 1545, type: 'application/json' }
res.status(response.status).send(blob);
}
I am calling this api from my component like:
const fetchWithToken = async (service, token) => {
// data fetch function in UI.
const response = await fetch(`${process.env.basePath}/${service}`, {
headers: { Authorization: `Bearer ${token}` },
});
const blob = await response.blob();
console.log("»»»»»» [DEBUG : response ] -- :", blob); // Blob {size: 2, type: 'application/json'}
// download as file logic ....
}
as you can see the blob in ui data fetch response gives a blob size of 2 (content will be an empty object) even if the expected size is bigger.
I tried to convert the blob to a readable stream and send it back to the ui from next api. also tried to make use of File()
. both idea failed.
I was able to convert the blob to text in api (blob.text()
) and send it as the response; but it will work only for json,csv,etc... files. But the scope is wide.
I am using nextjs - 13.5.4 node - 18.17.1.
I would prefer to send the file from UI_ENGINE
to frontend directly. Please help me to find the best solution. thanks in advance...
In the Next.js API handler function, after reading the response blob from the respective API, I attempted to convert it into a stream, array buffer, and file to send the response back to the reading function properly. However, none of these methods worked well. Since I couldn't pinpoint the exact issue, I tried converting the blob to raw buffer and sending it as a response, which surprisingly worked.
To do this first convert the blob to and array buffer -
const arrayBuffer = await blob.arrayBuffer();
then use the arraybuffer to create new raw buffer - const buffer = Buffer.from(arrayBuffer);
Since I am sending a file it is important to include some key headers along with the response
export default async function handler(req, res) {
const endpoint = `${process.env.UI_ENGINE}/docs/${req.query.id}/download-doc`;
try {
const response = await fetch(endpoint, {
headers: { Authorization: `${req.headers.authorization}` },
});
const blob = await response.blob();
const contentType =
response.headers.get("content-type") || "application/octet-stream";
const contentLength = response.headers.get("content-length") || blob.size;
// converting blob to raw buffer for transferring
// (other formats including blob was not working)
const arrayBuffer = await blob.arrayBuffer();
const buffer = Buffer.from(arrayBuffer);
res
.status(200)
.setHeader("Content-Type", contentType)
.setHeader("Content-Length", contentLength)
.send(buffer);
} catch (error) {
res.status(500).send({ message: "Error fetching the document", error });
}
}
I am not expecting this to be the exact solution. There has to be a better way to do this.