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
}
}
}
fetch(url, { body: new File(...) })in the end