MOBILE-3270 core: Fix upload files from Google Drive

main
Dani Palou 2020-04-07 12:22:47 +02:00
parent f819331f50
commit ec3a1bdb56
3 changed files with 38 additions and 18 deletions

View File

@ -78,7 +78,7 @@ export class CoreLocalFileComponent implements OnInit {
this.size = this.textUtils.bytesToSize(metadata.size, 2); this.size = this.textUtils.bytesToSize(metadata.size, 2);
} }
this.timemodified = this.timeUtils.userDate(metadata.modificationTime, 'core.strftimedatetimeshort'); this.timemodified = this.timeUtils.userDate(metadata.modificationTime.getTime(), 'core.strftimedatetimeshort');
}); });
} }

View File

@ -18,6 +18,7 @@ import { CoreFileProvider } from '@providers/file';
import { CoreDomUtilsProvider } from '@providers/utils/dom'; import { CoreDomUtilsProvider } from '@providers/utils/dom';
import { CoreTextUtilsProvider } from '@providers/utils/text'; import { CoreTextUtilsProvider } from '@providers/utils/text';
import { CoreTimeUtilsProvider } from '@providers/utils/time'; import { CoreTimeUtilsProvider } from '@providers/utils/time';
import { MediaFile } from '@ionic-native/media-capture';
/** /**
* Page to capture media in browser or desktop. * Page to capture media in browser or desktop.
@ -364,13 +365,21 @@ export class CoreEmulatorCaptureMediaPage implements OnInit, OnDestroy {
if (this.isImage && !this.isCaptureImage) { if (this.isImage && !this.isCaptureImage) {
this.dismissWithData(fileEntry.toURL()); this.dismissWithData(fileEntry.toURL());
} else { } else {
// The capture plugin returns a MediaFile, not a FileEntry. // The capture plugin should return a MediaFile, not a FileEntry. Convert it.
// The only difference is that it supports a new function that won't be supported in desktop. return this.fileProvider.getMetadata(fileEntry).then((metadata) => {
fileEntry.getFormatData = (successFn, errorFn): any => { const mediaFile: MediaFile = {
// Nothing to do. name: fileEntry.name,
}; fullPath: fileEntry.fullPath,
type: null,
lastModifiedDate: metadata.modificationTime,
size: metadata.size,
getFormatData: (successFn, errorFn): void => {
// Nothing to do.
}
};
this.dismissWithData([fileEntry]); this.dismissWithData([mediaFile]);
});
} }
}).catch((err) => { }).catch((err) => {
this.domUtils.showErrorModal(err); this.domUtils.showErrorModal(err);

View File

@ -14,7 +14,7 @@
import { Injectable } from '@angular/core'; import { Injectable } from '@angular/core';
import { Platform } from 'ionic-angular'; import { Platform } from 'ionic-angular';
import { File, FileEntry, DirectoryEntry } from '@ionic-native/file'; import { File, FileEntry, DirectoryEntry, Entry, Metadata } from '@ionic-native/file';
import { CoreAppProvider } from './app'; import { CoreAppProvider } from './app';
import { CoreLoggerProvider } from './logger'; import { CoreLoggerProvider } from './logger';
@ -545,7 +545,7 @@ export class CoreFileProvider {
reader.onloadend = (evt): void => { reader.onloadend = (evt): void => {
const target = <any> evt.target; // Convert to <any> to be able to use non-standard properties. const target = <any> evt.target; // Convert to <any> to be able to use non-standard properties.
if (target.result !== undefined || target.result !== null) { if (target.result !== undefined && target.result !== null) {
if (format == CoreFileProvider.FORMATJSON) { if (format == CoreFileProvider.FORMATJSON) {
// Convert to object. // Convert to object.
const parsed = this.textUtils.parseJSON(target.result, null); const parsed = this.textUtils.parseJSON(target.result, null);
@ -558,7 +558,7 @@ export class CoreFileProvider {
} else { } else {
resolve(target.result); resolve(target.result);
} }
} else if (target.error !== undefined || target.error !== null) { } else if (target.error !== undefined && target.error !== null) {
reject(target.error); reject(target.error);
} else { } else {
reject({ code: null, message: 'READER_ONLOADEND_ERR' }); reject({ code: null, message: 'READER_ONLOADEND_ERR' });
@ -602,7 +602,7 @@ export class CoreFileProvider {
* @param append Whether to append the data to the end of the file. * @param append Whether to append the data to the end of the file.
* @return Promise to be resolved when the file is written. * @return Promise to be resolved when the file is written.
*/ */
writeFile(path: string, data: any, append?: boolean): Promise<any> { writeFile(path: string, data: any, append?: boolean): Promise<FileEntry> {
return this.init().then(() => { return this.init().then(() => {
// Remove basePath if it's in the path. // Remove basePath if it's in the path.
path = this.removeStartingSlash(path.replace(this.basePath, '')); path = this.removeStartingSlash(path.replace(this.basePath, ''));
@ -635,15 +635,18 @@ export class CoreFileProvider {
* @param append Whether to append the data to the end of the file. * @param append Whether to append the data to the end of the file.
* @return Promise resolved when done. * @return Promise resolved when done.
*/ */
writeFileDataInFile(file: any, path: string, onProgress?: (event: CoreFileProgressEvent) => any, offset: number = 0, async writeFileDataInFile(file: Blob, path: string, onProgress?: (event: CoreFileProgressEvent) => void, offset: number = 0,
append?: boolean): Promise<any> { append?: boolean): Promise<FileEntry> {
offset = offset || 0; offset = offset || 0;
// Get the chunk to read. // Get the chunk to read.
const blob = file.slice(offset, Math.min(offset + this.CHUNK_SIZE, file.size)); const readWholeFile = offset === 0 && this.CHUNK_SIZE >= file.size;
const chunk = readWholeFile ? file : file.slice(offset, Math.min(offset + this.CHUNK_SIZE, file.size));
try {
const fileEntry = await this.writeFileDataInFileChunk(chunk, path, append);
return this.writeFileDataInFileChunk(blob, path, append).then((fileEntry) => {
offset += this.CHUNK_SIZE; offset += this.CHUNK_SIZE;
onProgress && onProgress({ onProgress && onProgress({
@ -659,7 +662,15 @@ export class CoreFileProvider {
// Read the next chunk. // Read the next chunk.
return this.writeFileDataInFile(file, path, onProgress, offset, true); return this.writeFileDataInFile(file, path, onProgress, offset, true);
}); } catch (error) {
if (readWholeFile || !error || error.name != 'NotReadableError') {
return Promise.reject(error);
}
// Permission error when reading file in chunks. This usually happens with Google Drive files.
// Try to read the whole file at once.
return this.writeFileDataInFileChunk(file, path, false);
}
} }
/** /**
@ -670,7 +681,7 @@ export class CoreFileProvider {
* @param append Whether to append the data to the end of the file. * @param append Whether to append the data to the end of the file.
* @return Promise resolved when done. * @return Promise resolved when done.
*/ */
protected writeFileDataInFileChunk(chunkData: any, path: string, append?: boolean): Promise<any> { protected writeFileDataInFileChunk(chunkData: any, path: string, append?: boolean): Promise<FileEntry> {
// Read the chunk data. // Read the chunk data.
return this.readFileData(chunkData, CoreFileProvider.FORMATARRAYBUFFER).then((fileData) => { return this.readFileData(chunkData, CoreFileProvider.FORMATARRAYBUFFER).then((fileData) => {
// Write the data in the file. // Write the data in the file.
@ -1053,7 +1064,7 @@ export class CoreFileProvider {
* @param fileEntry FileEntry retrieved from getFile or similar. * @param fileEntry FileEntry retrieved from getFile or similar.
* @return Promise resolved with metadata. * @return Promise resolved with metadata.
*/ */
getMetadata(fileEntry: Entry): Promise<any> { getMetadata(fileEntry: Entry): Promise<Metadata> {
if (!fileEntry || !fileEntry.getMetadata) { if (!fileEntry || !fileEntry.getMetadata) {
return Promise.reject(null); return Promise.reject(null);
} }