I want to be able to upload multiple images to Firebase using React Typescript. The uploadBytes() is throwing some type error which I have been unable to resolve.
Below is my Code
type imageUploadType = {
lastModified: number,
lastModifiedDate: Date,
name: string,
size: string,
type: string,
webkitRelativePath: string
}
const initialUploadValues = {
lastModified: 1688490575474,
lastModifiedDate: new Date(),
name: "Gospel TV.png",
size: '24546',
type: "image/png",
webkitRelativePath: ""
}
const Modal = (props: IModalProps) => {
const user = useContext(UserContext)
const [imageUpload, setImageUpload] = useState<imageUploadType>(initialUploadValues);
const [imageUrls, setImageUrls] = useState<Array<string>>([]);
const imagesListRef = ref(storage, "images/");
const uploadFile = () => {
if (imageUpload == null) return;
const imageRef = ref(storage, `images/${imageUpload.name + v4()}`);
uploadBytes(imageRef, imageUpload).then((snapshot) => {
getDownloadURL(snapshot.ref).then((url) => {
setImageUrls((prev) => [...prev, url]);
});
});
};
}
Below is the error
Argument of type 'imageUploadType' is not assignable to parameter of type 'Blob | Uint8Array | ArrayBuffer'.
Type 'imageUploadType' is missing the following properties from type 'Blob': arrayBuffer, slice, stream, textts(2345) const imageUpload: imageUploadType
i tried adding a custom type for the imageUpload state and yet didnt work
Based on the docs found here, it looks like the function uploadBytes
is expecting a different datatype than you are passing into it. Here is a proposed solution by converting passed in data to a blob:
type imageUploadType = {
lastModified: number,
lastModifiedDate: Date,
name: string,
size: string,
type: string,
webkitRelativePath: string
}
const initialUploadValues = {
lastModified: 1688490575474,
lastModifiedDate: new Date(),
name: "Gospel TV.png",
size: '24546',
type: "image/png",
webkitRelativePath: ""
};
const Modal = (props: IModalProps) => {
const user = useContext(UserContext);
const [imageUpload, setImageUpload] = useState<imageUploadType>(initialUploadValues);
const [imageUrls, setImageUrls] = useState<Array<string>>([]);
const imagesListRef = ref(storage, "images/");
const convertToBlob = (file: File): Promise<Blob> => {
return new Promise((resolve, reject) => {
const reader = new FileReader();
reader.onloadend = () => {
const blob = new Blob([reader.result as ArrayBuffer], { type: file.type });
resolve(blob);
};
reader.onerror = reject;
reader.readAsArrayBuffer(file);
});
};
const uploadFile = async () => {
if (!imageUpload) return;
const { name } = imageUpload;
const file = new File([name], name, { type: imageUpload.type });
const blob = await convertToBlob(file);
const imageRef = ref(storage, `images/${imageUpload.name + v4()}`);
uploadBytes(imageRef, blob).then((snapshot) => {
getDownloadURL(snapshot.ref).then((url) => {
setImageUrls((prev) => [...prev, url]);
});
});
};
// Rest of your component code...
};
convertToBlob
is going to take in a file object and convert it into a blob object. The returned promise resolves with the resulting blob. uploadFile
now creates a file object using imageUpload
and passing it to the convertToBlob
function to obtain the converted Blob before uploading it to Firebase.
One thing to double check is the convertToBlob
function uses the FileReader API to read the file content. So you can swap this out with whatever else you're currently using to read files, or import it if you're not reading files at all right now.