[FIXED] Display file to user after conversion

Issue

I would like to write a service for converting files from one format to another (something similar at https://convertio.co/mp4-gif/) . I already have a file upload button that allows the user to upload a file from their device to the site. There is a box that displays the file name, size, desired format for conversion and a button to convert.
By pressing the convert button (ConvertFileButton) a request is sent to the backend.
And now I have a question: how can I get an already converted file from the backend and display it for the user (so that the user can download a new converted file)

Now in order:

below is the "CONVERT" button component that sends a request to the backend

export default function ConvertFileButton() {

  const { file } = useContext(AppContext)
  const formData = new FormData();
  formData.append('file', file);

  return (
    <MyButton onClick={() => { fetch('http://localhost:5000/transcript', 
    { method: 'post', body: formData }); }}>CONVERT</MyButton>
  )
}

Below I will present three functions on the backend that process the request. The backend is written in Python using Flask.

The first function to which the file is sent and in which the conversion takes place

    @mod.route('/transcript', methods=['POST', "GET"])
def create_transcript_task():
   return redirect(url_for('backend.status_page') + f'?id={task_id}')

then you can get the finished converted file

@mod.route('/get', methods=['GET'])
def get_result():
    return send_file(file_path)

Thus, I will explain the question: how can I display this finished file again in React, so that the user can download a new converted file.

As I understand it, you need to create a component in which to transfer this new file. But I don’t understand how to do it. Perhaps you can help me

    export default function DisplayConvertedFile() {

    return (
      // some code //
    )
  }

Solution

We can simplify the server as follows:

from flask import Flask, send_file

app = Flask(__name__)

@app.route('/get', methods=['GET'])
def get_result():
    response = send_file("hello.jpg")
    response.headers.add("Access-Control-Allow-Origin", "*")

    return response

app.run(debug=True)

This will serve the image at 127.0.0.1:5000/get similar to your situation (it assumes that there is an image called hello.jpg. Now we can display this in React by creating an URL from the data, this can be done as follows:

<html>
    <head>
        <script crossorigin src="https://unpkg.com/react@18/umd/react.development.js"></script>
        <script crossorigin src="https://unpkg.com/react-dom@18/umd/react-dom.development.js"></script>
    </head>

    <body>
        <div id="root"></div>
    </body>

    <script defer>
        function DisplayComponent(props) {
            const [dataUrl, setDataUrl] = React.useState(null);

            // There are several ways to convert the result of 'fetch' to an URL.
            // Refer to: https://stackoverflow.com/q/7650587/8746648
            fetch("http://127.0.0.1:5000/get")
                .then(response => response.blob())
                .then(blob => URL.createObjectURL(blob))
                .then(newDataUrl => setDataUrl(newDataUrl));

            return React.createElement("img", { src: dataUrl });
        }


        console.log(document.getElementById("root"));

        const root = ReactDOM.createRoot(document.getElementById("root"));
        root.render(React.createElement(DisplayComponent));
    </script>
</html>

I used the regular syntax here, because that is easier to reproduce.


EDIT:

To clear up some confusion, here is the same thing but in the JSX syntax. I also added a button to initiate the request since this caused confusion.

import {useState} from "react";

function DisplayComponent(props) {
    const [dataUrl, setDataUrl] = useState(null);

    function onClick() {
        // There are several ways to convert the result of 'fetch' to an URL.
        // Refer to: https://stackoverflow.com/q/7650587/8746648
        fetch("http://127.0.0.1:5000/get")
            .then(response => response.blob())
            .then(blob => URL.createObjectURL(blob))
            .then(newDataUrl => setDataUrl(newDataUrl));
    }

    return (
        <div>
            <button onClick={onClick}>Fetch</button>
            <img src={dataUrl} />
        </div>
    );
}

export default DisplayComponent;

EDIT 2:

I assumed you were dealing with an MP4 to GIF conversion because of the link in the question. If you have a general file, like a sound file you can just let the user download it:

// Copied from: https://stackoverflow.com/a/45905238/8746648
function download(dataurl, filename) {
  const link = document.createElement("a");
  link.href = dataurl;
  link.download = filename;
  link.click();
}

function onClick() {
    // There are several ways to convert the result of 'fetch' to an URL.
    // Refer to: https://stackoverflow.com/q/7650587/8746648
    fetch("http://127.0.0.1:5000/get")
        .then(response => response.blob())
        .then(blob => URL.createObjectURL(blob))
        .then(newDataUrl => download(newDataUrl, "filename.jpg"));
}

Answered By – asynts

Answer Checked By – Dawn Plyler (Easybugfix Volunteer)

Leave a Reply

(*) Required, Your email will not be published