1

I have to upload and read an excel file from UI and send the file data in binary form to a backend API.

I am using the File reader and reading the file as binary, like below, and passing the fileReader.result to my Node js controller for calling the API.

fileReader.readAsBinaryString(this.file);

At the backend this is throwing some error. When I am using fileReader.readAsArrayBuffer(this.file) ; I am not able to pass to the controller, since this is object, not a string.

How do I resolve this issue, I want to pass the data obtained from readAsArrayBuffer to the API.

3
  • 1
    you do not need to read the file as binaryString just upload/send the file as is Commented Jul 26, 2021 at 14:12
  • okay, but I am not able to send this.file in the API, I have to send it as string or buffer; how to do that? Commented Jul 27, 2021 at 11:57
  • I need more code to be able to help you, but basically it's going to end up with: fetch(url, { body: new File(...) }) in the end Commented Jul 27, 2021 at 18:00

1 Answer 1

1

Using Angular 2+, one way you can send the file to your server is using the FormData with HTTPClient (@angular/common/http). I'm presuming you are using TypeScript and when your clicking uploading you are calling a function called upload. So this is a simple example and you can take it as a reference and adapt to your case. The file will be sent as binary:

import { HttpClient } from '@angular/common/http';

export class MyFormService {

 constructor(private _http: HttpClient) {}

 upload(data: IDataModel): Promise<IMyServerResponse> {
    return new Promise(async (resolve, reject) => {
      const url = 'https://example.com/api/';

      const formData = new FormData();
     
     //If you have just an attachment consider this ---------------------------
     //As suggestion, encode or replace special characters from fileName.
     //The function this.parseFileName is basically doing it.
     const name = this.parseFileName(data.attachment.name);
     formData.append('attachment', data.attachment.file, name);
     //-----------------------------------------------------------------------


      //Or if you have multiple files, consider this one ---------------------
      //Pay attention to the [] after attachment;
      for (const item of data.attachmentList) {
        
        const name = this.parseFileName(item.name);
        formData.append('attachment[]', item.file, name);
      }
     //-----------------------------------------------------------------------

      //Here you post your form data with progress reporting -----------------
      await this._http.post(url, formData, { reportProgress: true, observe: 'events', responseType: 'json' })
        .subscribe(async event => {
            if (event.type === HttpEventType.UploadProgress) {
               //Here you can check the progress based on event.loaded 
               //divided by event.total and show to your user.
               
               //Code omitted 
               ...
               ...
            }

            if (event.type === HttpEventType.Sent) {
              //Here your data has been sent to the server.
              //So, based on your server, you can manipulate the request based on 
              //the form field.
            }

            if (event.type === HttpEventType.Response) {
              const serverResponse = event.body as IMyServerResponse;

              //Code omitted
              ...
              ...
              ...

              resolve(serverResponse);
            }
          },
          error => {
            let errorMessage;

            //Code omitted
            ...
            ...
            ...

            reject(error);
          });
    });
  }
}

Backend in PHP for receiving files:

<?php


namespace App\Http\Controllers;


use Exception;
use Illuminate\Http\JsonResponse;
use Illuminate\Http\Request;
use Illuminate\Http\Response;

abstract class BaseController extends Controller
{

  //Attachment
  /**
   * @throws Exception
   */
  public function retrieveAttachment(string $id): Response
  {
    $parsedId = intval($id);

    if (is_null($id)) {
      throw new Exception("Empty ID");
    } else if (!is_numeric($parsedId)) {
      throw new Exception("Invalid ID");
    }

    $data = $this->show($parsedId);

    // File type
    $file_type = mime_content_type($data->icon);
    $data->file_type = $file_type;

    //File extension
    $tmp = explode('.', $data->icon);
    $file_ext = strtolower(end($tmp));

    //File content
    $fileData = fopen($data->icon, 'rb');
    $size = filesize($data->icon);
    $fileContent = fread($fileData, $size);
    fclose($fileData);
    
    
    return response()->make($fileContent, 200, [
      'Cache-Control' => 'no-cache private',
      'Content-Type' => $file_type,
      'Content-length' => strlen($fileContent),
      'file_name' => $data->name,
      'file_type' => $file_type,
      'file_size' => $size,
      'file_ext' => $file_ext,
      'Content-Transfer-Encoding' => 'binary',
      'Access-Control-Expose-Headers' => 'file_name, file_type, file_size, file_ext'
    ]);
  }
}

Backend in Javascript/Angular for Sharepoint on premises (<= 2019)

import { Injectable } from '@angular/core';
import { Location } from '@angular/common';
import { ActivatedRoute } from '@angular/router';


import { SpCore } from 'my-beutiful-service.service';
import { sp } from '@pnp/sp/presets/core';
import "@pnp/sp/attachments";
//..
//..
//..
//.. other imports

@Injectable({
  providedIn: 'root'
})
export class CoreServicesDataSaveMainFormService {

  constructor(
  private _data: CoreServicesDataMainService,
  //...
  //...
  //Other components
  ) {}

    private populateFiles(attachmentsData: IAttachmentData[]): IAttachmentFileInfo[] {
        const attachments: IAttachmentFileInfo[] = [];
        const userAttachments: IAttachmentData[] = attachmentsData.filter(x => x.new);

        //This is the file received being prepared
        for (const attachment of userAttachments) {
          if (attachment.file != null) {
            const name = attachment.file.name;
            const content = new Blob([attachment.file], { type: attachment.file.type });
            attachments.push({ name, content });
          }
        }

        return attachments;
      }
    }

    private add(listItemId, listName, attachments, baseUrl) {
        const base = baseUrl == null ? SpCore.baseUrl : baseUrl;
        return new Promise((resolve, reject) => {
            sp.configure(SpCore.config, base).web.lists.getByTitle(listName).items.getById(listItemId).attachmentFiles.addMultiple(attachments)
                .then(() => {
                resolve({ code: 200, description: 'Success!', message: 'The attachments has been added successfully.' });
            })
                .catch(reason => {
                SpCore.showErrorLog(reason);
                reject([]);
            });
        });
    }

    private addAttachment(listItemId, listName, attachments, baseUrl) {
        const base = baseUrl == null ? SpCore.baseUrl : baseUrl;
        return new Promise((resolve, reject) => {
            sp.configure(SpCore.config, base).web.lists.getByTitle(listName).items.getById(listItemId).attachmentFiles.addMultiple(attachments)
            .then(() => {
                resolve({ code: 200, description: 'Success!', message: 'The attachments has been added successfully.' });
            })
            .catch(reason => {
                SpCore.showErrorLog(reason);
                reject([]);
            });
        });
    }

  async save() {
    const attachments: IAttachmentFileInfo[] = this.populateFiles(this._data.attachments);

    const data: IDatabaseFields = {
      field1: this._data.field1,
      field2: this._data.field2,
      field3: this._data.field3,
      field4: this._data.field4,
      field5: this._data.field5
    };

    try {
      //Creating item
      const iar: ItemAddResult | ISpCoreResult = await this.add(this._service.listName, data, this._environment.fullBaseUrl);
      this._loading.status('Item criado!');

      //Adding attachments to the sharepoint list item
      await this.addAttachment(id, this._service.listName, attachments, this._environment.fullBaseUrl);

      //Process
      this.processFinalEvents(returnToSource);      
    } catch (reason) {
      //..catch error
    } 
  }
}
Sign up to request clarification or add additional context in comments.

2 Comments

Can you post the backend code to recieve the file?
@MathiasNoack this would be based on your backend, but I'll add here in PHP which is pretty common for basic and cheap server. Let me know if you would like in javascript (also angular), but used within SharePoint on Premises (<=2019)

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.