How to upload an array of images

I have these methods for choosing and uploading the image, but I am not sure about where the error is, if it is in the code or in the API

const [imagens, setImagens] = useState([])

  function choseImage(event) {
    imagens.push(URL.createObjectURL(event.target.files[0]))
  }

  const upload = () => {
    const fd = new FormData();
    // imagens is the array of images
    fd.append('imagem', imagens)
    fetch('http://localhost:5000/api/Upload', fd)
      .then(res => {
        console.log(res)
      });
  }

here is the UploadController, the messege is: System.NullReferenceException: 'Object reference not set to an instance of an object.' file was null.

    [HttpPost]
    public async Task Post(IFormFile file)
    {
        var nomeArquivo = (file.FileName);
        var uploads = Path.Combine(Directory.GetCurrentDirectory(), "wwwRoot\\Upload", nomeArquivo);

        if (!Directory.Exists(uploads)) Directory.CreateDirectory(uploads);

        if (file.Length > 0)
        {
            using (var fileStream = new FileStream(Path.Combine(uploads, file.FileName), FileMode.Create))
            {
                await file.CopyToAsync(fileStream);
            }
        }
    }

this is my first freelance project, that is the last thing missing, Thanks in advance

Upvotes: 0

Views: 1046

Answers (1)

Ashraf Ali
Ashraf Ali

Reputation: 603

Your code is nearly complete with a couple of changes commented in the code below. In your React component you can do something like the following.

export const ImageFileUpload =  () => {
  
    const [images, setImages] = useState([]);
    
    const onFileChange = (files) => {
      setImages(f => [...f, ...files]);
    };
    
    const handleClick = (e) => {
        e.preventDefault();

        const formData = new FormData();
        for (let i = 0; i < images.length; i++) {
            // 'images' name of the formData values must match the action method param on your controller
            formData.append(`images`, images[i]);   
        }
        
        // Make sure you api is running on the same endpoint or you need to set up CORS
        fetch('https://localhost:5001/fileupload', {
            body: formData,
            method: "POST" // Make sure you add the method POST to your request when API is only accepting POST
        }).then(res => console.log(res));
    };
    
    return (
        <form>
            <input type="file" multiple={true} onChange={e => onFileChange(e.target.files)} />
            <button onClick={handleClick}>Upload</button>
        </form>
    )
};

Your controller should look like this.

[ApiController]
[Route("[controller]")]
public class FileUploadController : ControllerBase
{
    [HttpPost]
    // 1. The name of the parameter must match the name of the `formData`
    // 2. This method should take `List<IFormFile>`
    public async Task Upload(List<IFormFile> images)
    {
        foreach (var image in images)
        {
            var nomeArquivo = (image.FileName);
            var uploads = Path.Combine(Directory.GetCurrentDirectory(), "wwwRoot\\Upload\\", nomeArquivo);

            if (!Directory.Exists(uploads)) Directory.CreateDirectory(uploads);

            using (var fileStream = new FileStream(Path.Combine(uploads, image.FileName), FileMode.Create))
            {
                await image.CopyToAsync(fileStream);
            }
        }
    }
}

Upvotes: 2

Related Questions