0

I am trying to upload files from Next js 13 application to azure blob storage

I think my file is an object and it expects a blob or buffer, I tried doing that but not of much help either.

my component code

<script src="https://cdnjs.cloudflare.com/ajax/libs/react/16.6.3/umd/react.production.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/react-dom/16.6.3/umd/react-dom.production.min.js"></script>
"use client";

import { Button } from "@/components/ui/button";
import {
  Dialog,
  DialogContent,
  DialogDescription,
  DialogFooter,
  DialogHeader,
  DialogTitle,
  DialogTrigger,
} from "@/components/ui/dialog";
import { Input } from "@/components/ui/input";
import { Label } from "@/components/ui/label";
import { useToast } from "@/components/ui/use-toast";
import { DialogClose } from "@radix-ui/react-dialog";
import { useState } from "react";
import { ButtonLoading } from "../LoadingButton";
import axios from 'axios';


export default function UploadData() {
  const [file, setFile] = useState<File | null>(null);
  const [isLoading, setIsLoading] = useState(false);
  const { toast } = useToast();


  const handleUrlInput = (event: React.ChangeEvent<HTMLInputElement>) => {
    const selectedFile = event.target.files?.[0]
    if (selectedFile) {
      setFile(selectedFile);
    }
  };

  const handleSubmit = async () => {

      const formData = new FormData();
      if (file) {
        formData.append('file', file);
      }
      console.log(formData)


    const response = axios.post('/api/ingest', formData, {
      headers: {
        'Content-Type': 'multipart/form-data',
      },
    })

    // Handle the response
    if ((await response).status === 200) {
      // File uploaded successfully
      console.log('File uploaded successfully!');
    } else {
      // Something went wrong
      console.log('Error uploading file:', response);
    }
  }

  return (
    <Dialog>
      <DialogTrigger asChild>
        {isLoading ? <ButtonLoading /> : <Button>Upload</Button>}
      </DialogTrigger>
      <DialogContent className="sm:max-w-[425px]">
        <DialogHeader>
          <DialogTitle>Edit profile</DialogTitle>
          <DialogDescription>
            Enter URL which you want to provide as input for retrieving
            information.
          </DialogDescription>
        </DialogHeader>
        <div className="grid gap-4 py-4">
          <div className="grid grid-cols-4 items-center gap-4">
            <Label htmlFor="name">URL</Label>
            <Input
              id="name"
              type="file"
              onChange={handleUrlInput}
              className="col-span-full"
            />
          </div>
        </div>
        <DialogFooter>
          <DialogClose asChild>
            <Button
              type="submit"
              onClick={handleSubmit}
            >
              Submit
            </Button>
          </DialogClose>
        </DialogFooter>
      </DialogContent>
    </Dialog>
  );
}

My API code

export async function POST(request: Request, res: Response) {
  try {
    // const file = (await request.formData())?.get("file") as Blob;
    const formData = await request.formData();
    const filePart = formData.get("file");
    console.log("filePart", typeof filePart);

    if (filePart instanceof Blob) {
      const fileName = filePart.name;
      const buffer = Buffer.from(await filePart.arrayBuffer());
      console.log("File Name:", fileName);
      console.log("Buffer:", buffer);
      const blobClient = containerClient.getBlockBlobClient(fileName);
      await blobClient.uploadData(buffer);
      return NextResponse.json(res);
    } else {
      console.log("Invalid file format");
      return NextResponse.error();
    }
  } catch (e) {
    console.log(e);
    return NextResponse.error();
  }
}

I am not able to upload files, the error displayed is Invalid file format:

⨯ RangeError [ERR_HTTP_INVALID_STATUS_CODE]: Invalid status code: 0

1 Answer 1

1

I am not able to upload files, the error displayed is:

Invalid file format ⨯ RangeError [ERR_HTTP_INVALID_STATUS_CODE]: Invalid status code: 0

According to this SO-thread by Gaurav Mantri, Azure blob storage doesn't support the multipart/form-data content type.

To upload multiple files you can use application/octet-stream or if you need to upload an image you can use the content-type= image/jpeg

Here is a sample code that I tried to upload images to Azure blob storage using the next.js app.

Code:

azconnect.js

import { BlobServiceClient } from '@azure/storage-blob';

const connectionString = process.env.AZURE_CONNECTION;
const blobServiceClient = BlobServiceClient.fromConnectionString(connectionString);
const containerName = process.env.AZURE_CONTAINER_NAME;

async function uploadImageToAzureStorage(fileBuffer, fileName, contentType) {
  const containerClient = blobServiceClient.getContainerClient(containerName);
  const blockBlobClient = containerClient.getBlockBlobClient(fileName);

  try {
    await blockBlobClient.uploadData(
      fileBuffer,
      {
        blobHTTPHeaders: { blobContentType: contentType },
      }
    );

    return blockBlobClient.url;
  } catch (error) {
    console.error('Error uploading image:', error);
    throw error;
  }
}

export { uploadImageToAzureStorage }

Components:

import { useState } from 'react';

const ImageUploadForm = () => {
  const [image, setImage] = useState(null);

  const handleSubmit = (e) => {
    const reader = new FileReader();
    reader.readAsDataURL(e.target.files[0]);

    reader.onload = () => {
      setImage(reader.result);
    };
    reader.onerror = () => {
      console.log('reader.error', reader.error);
    };
  };

  const uploadImage = async () => {
    try {
      const headers = {
        'Content-Type': 'image/jpeg', 
      };

      const response = await fetch('/api/postImage', {
        method: 'POST',
        body: image,
        headers: headers,
      });

      if (response.ok) {
        console.log('Image uploaded successfully!');
      } else {
        console.error('Image upload failed.');
      }
    } catch (error) {
      console.error('Error uploading image:', error);
    }
  };

  return (
    <>
      <input type="file" accept="image/*" onChange={handleSubmit} />
      <button onClick={uploadImage}>Upload Image</button>
    </>
  );
};

export default ImageUploadForm;

Browser: enter image description here

Portal: enter image description here

Here is my GitHub link of the entire project to upload a sample image file to Azure blob storage using next.js.

Sign up to request clarification or add additional context in comments.

Comments

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.