Search code examples
javascriptreactjsbinaryfilesreact-md

ArrayBuffer to binary image file


I am using a react component as my MarkDown editor. This component provided a dropzone to paste in files and it accepts a callback function which is passed ArrayBuffer of the file (mainly image file). The backend expects an image file as if uploaded by a form. But having ArrayBuffer returned instead of the file has proven to be a bit of an issue.

I have attempted to convert the ArrayBuffer to a Blob, still, the backend needs other info from the file uploaded such as filename and size which exist on the binary image file. I'd appreciate any help! Thank you.

Example below:

function converArrayBufferToImage(ab) {
    // Obtain a blob: URL for the image data.
    return new Blob([ab])
}

export default function ReactMdEditor(props) {
    const { value, setValue } = props;

    const save = async function* (file) {
        let fileData = new FormData()
        let convertedFile = converArrayBufferToImage(file)
        fileData.append('file', convertedFile);
        try {
            const response = yield uploadFile(fileData);
            const data = response.data;
            yield data.url;
            return true;
        } catch (error) {
            console.log(error);
            return false;
        }
    };

    return (
        <div>
            <ReactMde
                value={value}
                onChange={setValue}
                childProps={{
                    writeButton: {
                        tabIndex: -1
                    }
                }}
                paste={{
                    saveImage: save
                }}
            />
        </div>
    );
}

Edit: if needed for context, my backend is build with Python, Flask.


Solution

  • Alright, it seems I have found a solution.

    Here is the save function now:

        const save = async function* (file) {
        try {
            const blobFile = new Blob([file], { "type": "image/png" });
            let formData = new FormData()
            formData.append('file', blobFile, 'file.png');
            try {
                const response = await uploadFile(formData);
                const data = response.data;
                yield data.url;
                return true;
            } catch (error) {
                console.log(error);
                return false;
            }
        } catch (e) {
            console.warn(e.message)
            return false;
        }
    };
    

    You'll need to generate a unique filename on the client or server in order to not overwrite existing files with same name if you are not already.

    explanation of what this function does if anyone needs that: if simply gets passed an array buffer, converts it to an image Blob, and it uploads it to the server, the latter returning the url where the file was saved. I hope this helps someone and saves them sometime.