How to upload attachment to server ,Net Core+React(Redux)

Viewed 492

I would like to add an attachment, I use .net core 2.0 and react(redux). On backend i have ORM db EF. This is Model:

    public byte[] Attachment { get; set; }

My attachment is in byte[] on backend. This is my React code: Function:

   fileSelectedHandler = event => {
    this.setState({
        attachment: event.target.files[0]
    })
}

Constructor:

 this.state = {
   attachment: null
 }

onSubmit:

    const fd = new FormData();
     const test = fd.append('attachment', this.state.attachment, 
     this.state.attachment.name);

     const reportData = {
            attachment: test
        };
    this.props.addReport(reportData, url);

Unfortunately, it does not work, I have no idea to solve this problem.

SOLUTION:

    fileSelectedHandler = event => {
        let reader = new FileReader();
        reader.readAsDataURL(event.target.files[0]);
        if(event.target.files[0].size < 2097152){ // max 2mb files
            reader.onloadend = () => {
                this.setState({
                    attachment : reader.result.split(';base64,')[1]
                }) 
            };
        }
        else{
            tost.error('Plik powinien być mniejszy niż 2mb.'); // tost.error for file should be smaller than 2mb
            reader.onloadend = () => {
                this.setState({
                    attachment : null
                }) 
            };
        }

ReportAction:

  // Add Report
     export const addReport = (postData, prevUrl) => dispatch => {
      const config = {
    headers: {
      'enctype' : 'multipart/form-data' // it's important!
    }
  }
    axios
      .post(`${API_ROUTE}/api/Reports`, postData, config)
      .then( () => {
        const toastrOptions = {
          timeOut: 2000
        }
        if(prevUrl === "/reports"){
          dispatch(getReports())
        }
        tost.success('Pomyślnie dodano raport', toastrOptions);
      })
      .catch(err => {
        tost.error(err.response.data.errorMessage);
        dispatch({
          type: GET_ERRORS,
          payload: err.response.data
        })}
      );
};

Backend Controller:

    [AllowAnonymous]
    [HttpPost]
    public async Task<IActionResult> Add([FromBody] ReportDto reportDto)
    {
        var report = _mapper.Map<ReportDto, Report>(reportDto);

        var addedReport = await _service.AddReport(report);

        var uri = Request.PathBase.Value.ToString();

        return Created(uri, addedReport);
    }

ReportDto is the includ same props above.

1 Answers

First you have to change your chosen file attachment to form Data

function toFormData(file: File) {
    const data = new FormData();
    data.append("file", file);
    return data;
}

Then you have to submit your form data using sth like this:

async function uploadFile(url: string, file: File, onProgress?: (progress: number) => void) {
    const data = toFormData(file);
    const xhr = new XMLHttpRequest();
    return new Promise((resolve, reject) => {
        if (typeof onProgress === "function") {
            xhr.upload.onprogress = event => {
                onProgress(event.loaded / event.total);
            };
        }

        xhr.onload = () => {
            let response;
            try {
                response = JSON.parse(xhr.response);
            } catch (err) {
                response = xhr.response;
            }

            if (xhr.status >= 200 && xhr.status < 300) {
                resolve(response);
                return;
            }
            reject(response);
        };

        xhr.onerror = err => {
            reject(err);
        };

        xhr.open("POST", url);
        xhr.send(data);
    });
}

And finally you can consume your submitted attachment in Action using IFormFile intraface:

[HttpPost]
[Route("Attachment")]
public async Task Attachment([FromForm] IFormFile file)
{
    // do sth with attachment
}

Related