Skip to content

Commit

Permalink
Merge pull request #3881 from alfonso-salces/MOBILE-4481
Browse files Browse the repository at this point in the history
MOBILE-4481 ws.ts: Get mimetype from file transfer headers
  • Loading branch information
dpalou authored Feb 2, 2024
2 parents c79e77f + 8f2c344 commit 0541415
Show file tree
Hide file tree
Showing 9 changed files with 89 additions and 110 deletions.
24 changes: 7 additions & 17 deletions package-lock.json

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

1 change: 0 additions & 1 deletion package.json
Original file line number Diff line number Diff line change
Expand Up @@ -61,7 +61,6 @@
"@awesome-cordova-plugins/diagnostic": "^6.6.0",
"@awesome-cordova-plugins/file": "^6.6.0",
"@awesome-cordova-plugins/file-opener": "^6.6.0",
"@awesome-cordova-plugins/file-transfer": "^6.6.0",
"@awesome-cordova-plugins/geolocation": "^6.6.0",
"@awesome-cordova-plugins/http": "^6.6.0",
"@awesome-cordova-plugins/in-app-browser": "^6.6.0",
Expand Down
6 changes: 0 additions & 6 deletions src/core/features/emulator/emulator.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import { Camera } from '@awesome-cordova-plugins/camera/ngx';
import { Clipboard } from '@awesome-cordova-plugins/clipboard/ngx';
import { File } from '@awesome-cordova-plugins/file/ngx';
import { FileOpener } from '@awesome-cordova-plugins/file-opener/ngx';
import { FileTransfer } from '@awesome-cordova-plugins/file-transfer/ngx';
import { Geolocation } from '@awesome-cordova-plugins/geolocation/ngx';
import { InAppBrowser } from '@awesome-cordova-plugins/in-app-browser/ngx';
import { LocalNotifications } from '@awesome-cordova-plugins/local-notifications/ngx';
Expand All @@ -34,7 +33,6 @@ import { CameraMock } from './services/camera';
import { ClipboardMock } from './services/clipboard';
import { FileMock } from './services/file';
import { FileOpenerMock } from './services/file-opener';
import { FileTransferMock } from './services/file-transfer';
import { GeolocationMock } from './services/geolocation';
import { InAppBrowserMock } from './services/inappbrowser';
import { LocalNotificationsMock } from './services/local-notifications';
Expand Down Expand Up @@ -75,10 +73,6 @@ import { SecureStorageMock } from '@features/emulator/classes/SecureStorage';
provide: FileOpener,
useFactory: (): FileOpener => CorePlatform.is('cordova') ? new FileOpener() : new FileOpenerMock(),
},
{
provide: FileTransfer,
useFactory: (): FileTransfer => CorePlatform.is('cordova') ? new FileTransfer() : new FileTransferMock(),
},
{
provide: Geolocation,
useFactory: (): Geolocation => CorePlatform.is('cordova') ? new Geolocation() : new GeolocationMock(),
Expand Down
3 changes: 2 additions & 1 deletion src/core/features/emulator/services/emulator-helper.ts
Original file line number Diff line number Diff line change
Expand Up @@ -18,7 +18,7 @@ import { CoreFile } from '@services/file';
import { File, makeSingleton } from '@singletons';
import { CoreLogger } from '@singletons/logger';
import { FileMock } from './file';
import { FileTransferErrorMock } from './file-transfer';
import { FileTransferErrorMock, FileTransferMock } from './file-transfer';

/**
* Helper service for the emulator feature. It also acts as an init handler.
Expand All @@ -39,6 +39,7 @@ export class CoreEmulatorHelperProvider {
*/
async load(): Promise<void> {
window.FileTransferError = FileTransferErrorMock;
window.FileTransfer = FileTransferMock;

const fileService = File.instance;

Expand Down
120 changes: 52 additions & 68 deletions src/core/features/emulator/services/file-transfer.ts
Original file line number Diff line number Diff line change
Expand Up @@ -13,9 +13,6 @@
// limitations under the License.

import { CoreTextUtils } from '@services/utils/text';
import { Injectable } from '@angular/core';
import { FileTransfer, FileTransferObject, FileUploadResult, FileTransferError } from '@awesome-cordova-plugins/file-transfer/ngx';

import { CoreFile } from '@services/file';

/**
Expand Down Expand Up @@ -43,40 +40,25 @@ export class FileTransferErrorMock implements FileTransferError {
/**
* Emulates the Cordova FileTransfer plugin in desktop apps and in browser.
*/
@Injectable()
export class FileTransferMock extends FileTransfer {

/**
* Creates a new FileTransferObjectMock object.
*
* @returns a new file transfer mock.
*/
create(): FileTransferObjectMock {
return new FileTransferObjectMock();
}

}

/**
* Emulates the FileTransferObject class in desktop apps and in browser.
*/
export class FileTransferObjectMock extends FileTransferObject {
export class FileTransferMock {

progressListener?: (event: ProgressEvent) => void;
source?: string;
target?: string;
xhr?: XMLHttpRequest;

protected reject?: (reason?: unknown) => void;
// eslint-disable-next-line @typescript-eslint/no-empty-function
onprogress: (event: ProgressEvent) => void = () => {};

errorCallback?: (error: FileTransferError) => void;

/**
* Aborts an in-progress transfer. The onerror callback is passed a FileTransferError
* object which has an error code of FileTransferError.ABORT_ERR.
*/
abort(): void {
abort(): void {
if (this.xhr) {
this.xhr.abort();
this.reject?.(
this.errorCallback?.(
new FileTransferErrorMock(FileTransferErrorMock.ABORT_ERR, this.source || '', this.target || '', 0, '', ''),
);
}
Expand All @@ -87,21 +69,28 @@ export class FileTransferObjectMock extends FileTransferObject {
*
* @param source URL of the server to download the file, as encoded by encodeURI().
* @param target Filesystem url representing the file on the device.
* @param successCallback Callback to execute if download the file sucessfully.
* @param errorCallback Callback to execute if an error happened downloading the file.
* @param trustAllHosts If set to true, it accepts all security certificates.
* @param options Optional parameters, currently only supports headers.
* @returns Returns a Promise that resolves to a FileEntry object.
*/
// eslint-disable-next-line @typescript-eslint/no-explicit-any
download(source: string, target: string, trustAllHosts?: boolean, options?: { [s: string]: any }): Promise<unknown> {
return new Promise((resolve, reject): void => {
download(
source: string,
target: string,
successCallback: (params: CoreFileTransferDownloadResponse) => void,
errorCallback: (error: FileTransferError) => void,
trustAllHosts?: boolean,
// eslint-disable-next-line @typescript-eslint/no-explicit-any
options?: Record<string, any>,
): void {
// Use XMLHttpRequest instead of HttpClient to support onprogress and abort.
const basicAuthHeader = this.getBasicAuthHeader(source);
const xhr = new XMLHttpRequest();

this.xhr = xhr;
this.source = source;
this.target = target;
this.reject = reject;
this.errorCallback = errorCallback;

if (basicAuthHeader) {
source = source.replace(this.getUrlCredentials(source) + '@', '');
Expand All @@ -124,13 +113,12 @@ export class FileTransferObjectMock extends FileTransferObject {
}

xhr.onprogress = (ev: ProgressEvent): void => {
if (this.progressListener) {
this.progressListener(ev);
}
this.onprogress(ev);
};

xhr.onerror = (): void => {
reject(new FileTransferErrorMock(-1, source, target, xhr.status, xhr.statusText, ''));
const error = new FileTransferErrorMock(-1, source, target, xhr.status, xhr.statusText, '');
errorCallback(error);
};

xhr.onload = async (): Promise<void> => {
Expand All @@ -141,28 +129,27 @@ export class FileTransferObjectMock extends FileTransferObject {
if (status < 200 || status >= 300) {
// Request failed. Try to get the error message.
response = await this.parseResponse(response);
const error = new FileTransferErrorMock(-1, source, target, xhr.status, response || xhr.statusText, '');

reject(new FileTransferErrorMock(-1, source, target, xhr.status, response || xhr.statusText, ''));

return;
return errorCallback(error);
}

if (!response) {
reject();
const error = new FileTransferErrorMock(-1, source, target, xhr.status, xhr.statusText, 'No response obtained');

return;
return errorCallback(error);
}

const basePath = CoreFile.getBasePathInstant();
target = target.replace(basePath, ''); // Remove basePath from the target.
target = target.replace(/%20/g, ' '); // Replace all %20 with spaces.

// eslint-disable-next-line promise/catch-or-return
CoreFile.writeFile(target, response).then(resolve, reject);
CoreFile.writeFile(target, response)
.then(entry =>
successCallback({ entry: entry as unknown as globalThis.FileEntry, headers: response.headers }))
.catch(error => errorCallback(error));
};

xhr.send();
});
}

/**
Expand Down Expand Up @@ -227,15 +214,6 @@ export class FileTransferObjectMock extends FileTransferObject {
return credentials && credentials[1];
}

/**
* Registers a listener that gets called whenever a new chunk of data is transferred.
*
* @param listener Listener that takes a progress event.
*/
onProgress(listener: (event: ProgressEvent) => void): void {
this.progressListener = listener;
}

/**
* Parse a response, converting it into text and the into an object if needed.
*
Expand Down Expand Up @@ -285,11 +263,17 @@ export class FileTransferObjectMock extends FileTransferObject {
*
* @param fileUrl Filesystem URL representing the file on the device or a data URI.
* @param url URL of the server to receive the file, as encoded by encodeURI().
* @param successCallback Callback to execute if upload the file sucessfully.
* @param errorCallback Callback to execute if an error happened uploading the file.
* @param options Optional parameters.
* @returns Promise that resolves to a FileUploadResult and rejects with FileTransferError.
*/
upload(fileUrl: string, url: string, options?: FileUploadOptions): Promise<FileUploadResult> {
return new Promise((resolve, reject): void => {
upload(
fileUrl: string,
url: string,
successCallback: (result: FileUploadResult) => void,
errorCallback: (error: FileTransferError) => void,
options?: FileUploadOptions,
): void {
const basicAuthHeader = this.getBasicAuthHeader(url);
let fileKey: string | undefined;
let fileName: string | undefined;
Expand Down Expand Up @@ -330,7 +314,6 @@ export class FileTransferObjectMock extends FileTransferObject {
// Adding a Content-Type header with the mimeType makes the request fail (it doesn't detect the token in the params).
// Don't include this header, and delete it if it's supplied.
delete headers['Content-Type'];

// Get the file to upload.
CoreFile.getFile(fileUrl).then((fileEntry) =>
CoreFile.getFileObjectFromFileEntry(fileEntry)).then((file) => {
Expand All @@ -345,42 +328,43 @@ export class FileTransferObjectMock extends FileTransferObject {
}

xhr.onprogress = (ev: ProgressEvent): void => {
if (this.progressListener) {
this.progressListener(ev);
}
this.onprogress(ev);
};

this.xhr = xhr;
this.source = fileUrl;
this.target = url;
this.reject = reject;
this.errorCallback = errorCallback;

xhr.onerror = (): void => {
reject(new FileTransferErrorMock(-1, fileUrl, url, xhr.status, xhr.statusText, ''));
const error = new FileTransferErrorMock(-1, fileUrl, url, xhr.status, xhr.statusText, '');
errorCallback(error);
};

xhr.onload = (): void => {
// Finished uploading the file.
resolve({
const result = {
bytesSent: file.size,
responseCode: xhr.status,
response: xhr.response,
headers: this.getHeadersAsObject(xhr),
});
};

// Finished uploading the file.
successCallback(result);
};

// Create a form data to send params and the file.
const fd = new FormData();
for (const name in params) {
fd.append(name, params[name]);
}
fd.append('file', file, fileName);

fd.append('file', file, fileName);
xhr.send(fd);

return;
}).catch(reject);
});
}).catch(error => errorCallback(error));
}

}

export type CoreFileTransferDownloadResponse = { entry: globalThis.FileEntry; headers: Record<string, string> | undefined };
3 changes: 0 additions & 3 deletions src/core/features/native/native.module.ts
Original file line number Diff line number Diff line change
Expand Up @@ -22,7 +22,6 @@ import { Device } from '@awesome-cordova-plugins/device/ngx';
import { Diagnostic } from '@awesome-cordova-plugins/diagnostic/ngx';
import { File } from '@awesome-cordova-plugins/file/ngx';
import { FileOpener } from '@awesome-cordova-plugins/file-opener/ngx';
import { FileTransfer } from '@awesome-cordova-plugins/file-transfer/ngx';
import { Geolocation } from '@awesome-cordova-plugins/geolocation/ngx';
import { HTTP } from '@awesome-cordova-plugins/http/ngx';
import { InAppBrowser } from '@awesome-cordova-plugins/in-app-browser/ngx';
Expand All @@ -47,7 +46,6 @@ export const CORE_NATIVE_SERVICES = [
Diagnostic,
File,
FileOpener,
FileTransfer,
Geolocation,
HTTP,
InAppBrowser,
Expand All @@ -73,7 +71,6 @@ export const CORE_NATIVE_SERVICES = [
Diagnostic,
File,
FileOpener,
FileTransfer,
Geolocation,
HTTP,
InAppBrowser,
Expand Down
Loading

0 comments on commit 0541415

Please sign in to comment.