Stream & Blob
Upload
In order to pass the binary data to the server, the content type- multipart/form-data must be required
The
multipart/form-data
content type is designed to allow for the transmission of binary data, such as files, over HTTP. With this content type, the data in the request body is divided into multiple parts, each identified by a unique boundary string. Each part contains a header and a body, where the body contains the binary data of the file.
const url = `${process.env.REACT_APP_IMAGE_SERVICE_URL}/api/images`;
const formData = new FormData();
formData.append("file", file);
formData.append("type", "hi");
const { data } = await axios.post(url, formData);
<form action="/upload" method="post" enctype="multipart/form-data">
<input type="text" name="text" value="text default" />
<input type="file" name="file1" />
<input type="file" name="file2" />
<button type="submit">Submit</button>
</form>
Streaming

For handling stream, e.g: server sent event, it is needed to handle it chunk by chunk and monitor its progress
Here are examples of fetch and axios version of handling streaming
const reader = res.body.getReader();
// let sum = 0;
const stream = new ReadableStream({
start(controller) {
return pump();
function pump() {
return reader.read().then(({ done, value }) => {
// When no more data needs to be consumed, close the stream
if (done) {
controller.close();
return;
}
// Enqueue the next data chunk into our target stream
controller.enqueue(value);
// Can Conduct the logic based on the current chunk data (value)
// console.log("value",value);
// sum+=value.length;
// console.log("sum",sum);
return pump();
});
}
},
});
const response = new Response(stream);
console.log(response);
return response.blob();
export default function App() {
const [overallText, setOverallText] = useState("");
const handleServerSentEvent = async () => {
let overallText = "";
const res = await axios({
url: "http://127.0.0.1:3001/test",
method: "POST",
responseType: "text",
headers: {
"Content-Type": "application/json"
},
// monitor the progress, show the chunk on ui
onDownloadProgress: (progressEvent) => {
const {target} = progressEvent.event;
console.log("responseText", target.response)
overallText += target.responseText;
setOverallText(overallText);
}
});
console.log("res", res.data)
console.log("overallText", overallText)
}
return (
<div className="bg-background text-foreground" >
<Button onClick={handleServerSentEvent}>Receive Server Sent Event</Button>
<p>{overallText}</p>
</div>
)
}
Blob / File
For handling file with authorization, there are several ways
Data Url
Can be used for download file without uploading to server
The format is
data:[<mediatype>][;base64],<data>
Media type: mime type, e.g: image/png
data: the encoded data in base64 format which is converted from file binary data
The text/plain data Hello, World! data:text/plain;base64,SGVsbG8sIFdvcmxkIQ== base64-encoded version of the above data:,Hello%2C%20World%21 // excel file data:application/vnd.openxmlformats-officedocument.spreadsheetml.sheet;base64, xxxx
Server UrlFile url that uploaded to server
Streaming can be allowed when using server url to download file
If authentication is needed, the hash can be get from api firstly, and then combine with server url to obtain the file, e.g: https://backend.com/test.txt?code=xxxxxx
Blob (Binary large object)Blob data is a file-like object of immutable, raw data; they can be read as text or binary data, or converted into stream
When the server api return binary file (e.g: file), the endpoint is actually a file url
Sometimes, we need to fetch data instead of using a tag with server url to download file directly, for example: need to pass token into header
We need to get the blob data from response, make good use of blob data to create another url to new a tag to download file
const downloadLink = document.createElement('a'); downloadLink.href = URL.createObjectURL(blob); console.log(downloadLink.href); // blob:https://localhost:3000/d84cc112-85a0-4e8e-8319-233403c9c69e downloadLink.download = "123.csv"; document.body.appendChild(downloadLink); downloadLink.click();
Here is the download example
import { Button } from "@/components/ui/button"
import useQuery from "./hooks/useQuery"
import axios from "axios";
import { useState } from "react";
export type Todo = {
userId: number;
id: number;
title: string;
completed: boolean;
}
export default function App() {
const handleFileDownload = async() => {
const res = await axios({
url: "http://127.0.0.1:3001/test/file",
method: "GET",
responseType: "blob",
// monitor the progress of the download
onDownloadProgress: (progressEvent) => {
const {event, total, loaded} = progressEvent
const {target} = event;
console.log("responseText", target.response)
// track the progress, loaded = downloaded, total = total file size
console.log("total", total)
console.log("loaded", loaded)
}
})
console.log("res", res.data)
const url = URL.createObjectURL(res.data);
const a = document.createElement("a");
a.href = url;
a.download = "file.pdf";
a.click();
URL.revokeObjectURL(url);
}
return (
<div className="bg-background text-foreground" >
{/* <Button>Click me</Button> */}
<Button onClick={handleFileDownload}>Download File</Button>
</div>
)
}
Last updated
Was this helpful?