If you are utilizing Angular 2+, a method to send files to your server is by using the FormData in conjunction with HTTPClient (@angular/common/http). Assuming you are working with TypeScript, and upon clicking upload, you trigger a function named upload. Below is a straightforward example that can serve as a starting point for your scenario. The file will be transmitted as binary data:
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 dealing with a single attachment, consider this approach ---------------------------
//For precaution, make sure to encode or replace any special characters in the fileName.
//The function this.parseFileName handles this task.
const name = this.parseFileName(data.attachment.name);
formData.append('attachment', data.attachment.file, name);
//-----------------------------------------------------------------------
//Alternatively, if handling multiple files, consider this method ---------------------
//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 while reporting progress -----------------
await this._http.post(url, formData, { reportProgress: true, observe: 'events', responseType: 'json' })
.subscribe(async event => {
if (event.type === HttpEventType.UploadProgress) {
//You can monitor the progress based on event.loaded
//divided by event.total and display it to the user.
//Code omitted
...
...
}
if (event.type === HttpEventType.Sent) {
//Indicates successful transmission of data to the server.
//Based on your server configuration, you can modify the request according to
//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);
});
});
}
}
PHP backend implementation 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'
]);
}
}
Javascript/Angular backend 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,
//...
//...
) {}
private populateFiles(attachmentsData: IAttachmentData[]): IAttachmentFileInfo[] {
const attachments: IAttachmentFileInfo[] = [];
const userAttachments: IAttachmentData[] = attachmentsData.filter(x => x.new);
//This prepares the received file
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
}
}
}