Handling file uploads and downloads

In this guide, we will learn how to upload and view a file.

Setting up Backend

Upload File

  1. Create a 'Blank Backend Function' file in main-features folder and name it as 'upload'.

  2. Paste the below code in 'upload.server.tsx'

upload.server.tsx
import {
    createBackendFunction,
    createRequestContext,
    utils,
} from "@magicjs.dev/backend"

export default createBackendFunction(async function () {
    createRequestContext(this)
        .uploader()
        .onFile((info, file) => {
            // Will get the file information from the parameter info.
            utils.saveFileToUserUploads("/", `image.jpg`, file)
        })
})
  • It calls the uploader method on the request context, which sets up functionality related to handling file uploads.

  • The onFile method is called, which sets up an event handler for when a file is uploaded. It takes a callback function (info, file) as an argument.

    • info contains information about the uploaded file.

    • file contains the uploaded file itself.

    • It uses the utils.saveFileToUserUploads function to save the uploaded file to a specified location in the user's uploads directory.

This code defines a backend function that handles file uploads. It uses the createRequestContext function to create a request context, sets up an uploader, and defines an event handler for handling file uploads.

Read File

  1. Create a 'Blank Backend Function' file and name it as 'getfile'.

  2. Paste the below code in 'getfile.server.tsx'

getfile.server.tsx
import { createBackendFunction, utils } from "@magicjs.dev/backend"

export default createBackendFunction(async function (fileName: string) {

    return utils.readFileFromUserUploads("/", fileName)

})
  • The readFileFromUserUploads method from the utils module is called with two arguments:

    • "/": This is the path to the user's upload folder.

    • fileName: This is the name of the file that needs to be read from the specified upload folder.

  • The function returns the result of the readFileFromUserUploads operation, which represents the content or data of the file being read.

Integrate in UI

  1. Create a 'Blank UI Component' file in a feature.

  2. Name the file 'upload' and give a suitable path. We are assigning the path: '/upload'.

  3. Paste the code given below in 'upload.tsx'.

upload.tsx
import React from "react"
import { createUploader, createSrc } from "@magicjs.dev/frontend"
import { Button, Input } from "antd"
import uploadServer from "./upload.server"
import getfileServer from "./getfile.server"

const fileSrc = createSrc(getfileServer)

export default function Component(props: any) {
    const { addFiles, upload, readyToUpload, uploadProgress, loading } =
        createUploader(uploadServer)
        
    return (
        <div>
            <Input
                type="file"
                onChange={(e) => {
                    addFiles(e.target.files)
                    // Adds selected files to the uploader instance
                }}
            />
            <Button
                onClick={() => upload()}
                disabled={loading === true || Boolean(readyToUpload) === false}
            >
                Upload: {uploadProgress}%
            </Button>

            <div>
                <img src={fileSrc.getLink("image.jpg")} alt="File Preview" />
            </div>
        </div>
    )
}
Expand for Tailwind styled code.
import React from "react"
import { createUploader, createSrc } from "@magicjs.dev/frontend"
import uploadServer from "./upload.server"
import getfileServer from "./getfile.server"

const fileSrc = createSrc(getfileServer)

export default function Component(props: any) {
  const [isImageSelected, setIsImageSelected] = React.useState(false);
  const [imageName, setImageName] = React.useState('');
  const { addFiles, upload, readyToUpload, uploadProgress, loading } =
    createUploader(uploadServer)

  return (
    <div className="flex flex-row items-center justify-start h-screen gap-10 p-10">
      <div className="flex flex-col gap-3">
        <div className="flex items-center gap-3 w-[300px]">
          <button
            className="h-[35px] font-medium text-[13px] bg-[#FFFFFF] text-[#1C274C] px-4 rounded-[5px] border border-[#E3E3E3] hover:opacity-70 active:scale-95"
            onClick={() => {
              const fileInput = document.getElementById('fileInput');
              if (fileInput) {
                fileInput.click();
              }
            }}
          >
            Choose File
          </button>
          <div className="text-gray-600 text-sm" id="fileInputLabel">
            {isImageSelected ? imageName : `No file chosen yet`}
          </div>
        </div>
        <input
          type="file"
          id="fileInput"
          className="sr-only"
          onChange={(e: any) => {
            const selectedFile = e.target.files?.[0];
            if (selectedFile && selectedFile.name) {
              const fileName = selectedFile.name.length > 20
                ? selectedFile.name.slice(0, 20) + '...'
                : selectedFile.name;

              const fileInputLabel = document.getElementById('fileInputLabel');

              if (fileInputLabel) {
                fileInputLabel.innerText = fileName;
              }
              // Adds selected files to the uploader instance
              addFiles(e.target.files);
              setImageName(fileName)
              setIsImageSelected(true)
            }
          }}
        />
        <button
          className='w-fit text-[20px] text-white bg-violet-500 border border-[#BFBFBF] rounded-[10px] p-3 disabled:bg-violet-300 disabled:cursor-not-allowed hover:opacity-70 active:scale-95'
          onClick={() => upload()}
          disabled={loading === true || Boolean(readyToUpload) === false}
        >
          Upload: {uploadProgress}%
        </button>
      </div>
      <div>
        <img className="w-400" src={fileSrc.getLink("image.jpg")} alt="File Preview" />
      </div>
    </div>
  )
}

The code may have significant modifications to enhance the styling of the input button.

  • It renders a file input (Input) and a button (Button) for file selection and upload, respectively.

  • The onChange event of the file input adds selected files to the uploader instance using the addFiles function.

  • The upload button is disabled if the loading state is true or readyToUpload is false.

  • It displays upload progress using the uploadProgress state.

  • It renders an image tag (img) with the source URL obtained from fileSrc.getLink("image.jpg"), displaying a preview of the uploaded file.

Choose a file to upload and click on the button 'Upload'. Refresh the page to view the uploaded file.


Ready to step into the role of a Product Owner?

Dive into our comprehensive course designed to equip you with the skills and knowledge needed to excel. Click here to embark on your journey towards becoming a proficient product owner and unlocking exciting career opportunities!


Last updated