Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

MOBILE-4481 ws.ts: Get mimetype from file transfer headers #3881

Merged
merged 1 commit into from
Feb 2, 2024
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
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