forked from EVOgeek/Vmeda.Online
		
	MOBILE-3270 core: Revert some changes and improve error handling
This commit is contained in:
		
							parent
							
								
									9057b62333
								
							
						
					
					
						commit
						e80fa8dd18
					
				| @ -19,7 +19,6 @@ import { Camera, CameraOptions } from '@ionic-native/camera'; | ||||
| import { TranslateService } from '@ngx-translate/core'; | ||||
| import { CoreAppProvider } from '@providers/app'; | ||||
| import { CoreFileProvider, CoreFileProgressEvent } from '@providers/file'; | ||||
| import { CoreFileHelperProvider } from '@providers/file-helper'; | ||||
| import { CoreLoggerProvider } from '@providers/logger'; | ||||
| import { CoreDomUtilsProvider } from '@providers/utils/dom'; | ||||
| import { CoreTextUtilsProvider } from '@providers/utils/text'; | ||||
| @ -48,8 +47,7 @@ export class CoreFileUploaderHelperProvider { | ||||
|             protected actionSheetCtrl: ActionSheetController, | ||||
|             protected uploaderDelegate: CoreFileUploaderDelegate, | ||||
|             protected camera: Camera, | ||||
|             protected platform: Platform, | ||||
|             protected fileHelper: CoreFileHelperProvider) { | ||||
|             protected platform: Platform) { | ||||
|         this.logger = logger.getInstance('CoreFileUploaderProvider'); | ||||
|     } | ||||
| 
 | ||||
| @ -108,7 +106,7 @@ export class CoreFileUploaderHelperProvider { | ||||
|             const filePath = this.textUtils.concatenatePaths(CoreFileProvider.TMPFOLDER, newName); | ||||
| 
 | ||||
|             // Write the data into the file.
 | ||||
|             return this.fileHelper.writeFileDataInFile(file, filePath, (progress: CoreFileProgressEvent) => { | ||||
|             return this.fileProvider.writeFileDataInFile(file, filePath, (progress: CoreFileProgressEvent) => { | ||||
|                 this.showProgressModal(modal, 'core.fileuploader.readingfileperc', progress); | ||||
|             }); | ||||
|         }).catch((error) => { | ||||
| @ -193,9 +191,7 @@ export class CoreFileUploaderHelperProvider { | ||||
|             } | ||||
|         }); | ||||
| 
 | ||||
|         this.domUtils.showErrorModal(errorMessage); | ||||
| 
 | ||||
|         return Promise.reject(null); | ||||
|         return Promise.reject(errorMessage); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
| @ -649,7 +645,7 @@ export class CoreFileUploaderHelperProvider { | ||||
|                         this.fileProvider.removeExternalFile(path); | ||||
|                     } | ||||
| 
 | ||||
|                     return Promise.reject(null); | ||||
|                     return Promise.reject(this.domUtils.createCanceledError()); | ||||
|                 }); | ||||
|             }; | ||||
| 
 | ||||
|  | ||||
| @ -15,16 +15,13 @@ | ||||
| import { Injectable } from '@angular/core'; | ||||
| import { TranslateService } from '@ngx-translate/core'; | ||||
| import { CoreAppProvider } from './app'; | ||||
| import { CoreConfigProvider } from './config'; | ||||
| import { CoreFileProvider, CoreFileProgressFunction } from './file'; | ||||
| import { CoreFileProvider } from './file'; | ||||
| import { CoreFilepoolProvider } from './filepool'; | ||||
| import { CoreSitesProvider } from './sites'; | ||||
| import { CoreWSProvider } from './ws'; | ||||
| import { CoreDomUtilsProvider } from './utils/dom'; | ||||
| import { CoreUrlUtils } from './utils/url'; | ||||
| import { CoreUtilsProvider } from './utils/utils'; | ||||
| import { CoreConstants } from '@core/constants'; | ||||
| import { FileEntry } from '@ionic-native/file'; | ||||
| import { makeSingleton } from '@singletons/core.singletons'; | ||||
| 
 | ||||
| /** | ||||
| @ -33,23 +30,13 @@ import { makeSingleton } from '@singletons/core.singletons'; | ||||
| @Injectable() | ||||
| export class CoreFileHelperProvider { | ||||
| 
 | ||||
|     // Variables for reading files in chunks.
 | ||||
|     protected MAX_CHUNK_SIZE_NAME = 'file_max_chunk_size'; | ||||
|     protected READ_CHUNK_ATTEMPT_NAME = 'file_read_chunk_attempt'; | ||||
|     protected maxChunkSize = -1; | ||||
| 
 | ||||
|     constructor(protected fileProvider: CoreFileProvider, | ||||
|             protected filepoolProvider: CoreFilepoolProvider, | ||||
|             protected sitesProvider: CoreSitesProvider, | ||||
|             protected appProvider: CoreAppProvider, | ||||
|             protected translate: TranslateService, | ||||
|             protected utils: CoreUtilsProvider, | ||||
|             protected wsProvider: CoreWSProvider, | ||||
|             protected configProvider: CoreConfigProvider, | ||||
|             protected domUtils: CoreDomUtilsProvider) { | ||||
| 
 | ||||
|         this.initMaxChunkSize(); | ||||
|     } | ||||
|             protected wsProvider: CoreWSProvider) { } | ||||
| 
 | ||||
|     /** | ||||
|      * Convenience function to open a file, downloading it if needed. | ||||
| @ -258,34 +245,6 @@ export class CoreFileHelperProvider { | ||||
|         return file.timemodified || 0; | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Initialize the max chunk size. | ||||
|      * | ||||
|      * @return Promise resolved when done. | ||||
|      */ | ||||
|     protected async initMaxChunkSize(): Promise<void> { | ||||
|         const sizes = await Promise.all([ | ||||
|             await this.configProvider.get(this.READ_CHUNK_ATTEMPT_NAME, -1), // Check if there is any attempt pending.
 | ||||
|             await this.configProvider.get(this.MAX_CHUNK_SIZE_NAME, -1), // Retrieve current max chunk size from DB.
 | ||||
|         ]); | ||||
| 
 | ||||
|         const attemptSize = sizes[0]; | ||||
|         const maxChunkSize = sizes[1]; | ||||
| 
 | ||||
|         if (attemptSize != -1 && (maxChunkSize == -1 || attemptSize < maxChunkSize)) { | ||||
|             // Store the attempt's size as the max size.
 | ||||
|             this.storeMaxChunkSize(attemptSize); | ||||
|         } else { | ||||
|             // No attempt or the max size is already lower. Keep current max size.
 | ||||
|             this.maxChunkSize = maxChunkSize; | ||||
|         } | ||||
| 
 | ||||
|         if (attemptSize != -1) { | ||||
|             // Clean pending attempt.
 | ||||
|             await this.configProvider.delete(this.READ_CHUNK_ATTEMPT_NAME); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Check if a state is downloaded or outdated. | ||||
|      * | ||||
| @ -380,99 +339,6 @@ export class CoreFileHelperProvider { | ||||
| 
 | ||||
|         throw new Error('Couldn\'t determine file size: ' + file.fileurl); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Save max chunk size. | ||||
|      * | ||||
|      * @param size Size to store. | ||||
|      * @return Promise resolved when done. | ||||
|      */ | ||||
|     protected async storeMaxChunkSize(size: number): Promise<void> { | ||||
|         this.maxChunkSize = size; | ||||
| 
 | ||||
|         await this.configProvider.set(this.MAX_CHUNK_SIZE_NAME, size); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Write some file data into a filesystem file. | ||||
|      * It's done in chunks to prevent crashing the app for big files. | ||||
|      * | ||||
|      * @param file The data to write. | ||||
|      * @param path Path where to store the data. | ||||
|      * @param onProgress Function to call on progress. | ||||
|      * @param offset Offset where to start reading from. | ||||
|      * @param append Whether to append the data to the end of the file. | ||||
|      * @return Promise resolved when done. | ||||
|      */ | ||||
|     async writeFileDataInFile(file: Blob, path: string, onProgress?: CoreFileProgressFunction, offset: number = 0, | ||||
|             append?: boolean): Promise<FileEntry> { | ||||
| 
 | ||||
|         offset = offset || 0; | ||||
| 
 | ||||
|         // Get the chunk to read and write.
 | ||||
|         const readWholeFile = offset === 0 && CoreFileProvider.CHUNK_SIZE >= file.size; | ||||
|         const chunk = readWholeFile ? file : file.slice(offset, Math.min(offset + CoreFileProvider.CHUNK_SIZE, file.size)); | ||||
| 
 | ||||
|         try { | ||||
|             const fileEntry = await this.fileProvider.writeFileDataInFileChunk(chunk, path, append); | ||||
| 
 | ||||
|             offset += CoreFileProvider.CHUNK_SIZE; | ||||
| 
 | ||||
|             onProgress && onProgress({ | ||||
|                 lengthComputable: true, | ||||
|                 loaded: offset, | ||||
|                 total: file.size | ||||
|             }); | ||||
| 
 | ||||
|             if (offset >= file.size) { | ||||
|                 // Done, stop.
 | ||||
|                 return fileEntry; | ||||
|             } | ||||
| 
 | ||||
|             // Read the next chunk.
 | ||||
|             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.writeBigFileDataInFile(file, path, onProgress); | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Writes a big file data into a filesystem file without using chunks. | ||||
|      * The app can crash when doing this with big files, so this function will try to control the max size that works | ||||
|      * and warn the user if he's trying to upload a file that is too big. | ||||
|      * | ||||
|      * @param file The data to write. | ||||
|      * @param path Path where to store the data. | ||||
|      * @param onProgress Function to call on progress. | ||||
|      * @return Promise resolved with the file. | ||||
|      */ | ||||
|     protected async writeBigFileDataInFile(file: Blob, path: string, onProgress?: CoreFileProgressFunction): Promise<FileEntry> { | ||||
|         if (this.maxChunkSize != -1 && file.size >= this.maxChunkSize) { | ||||
|             // The file size is bigger than the max allowed size. Ask the user to confirm.
 | ||||
|             await this.domUtils.showConfirm(this.translate.instant('core.confirmreadfiletoobig')); | ||||
|         } | ||||
| 
 | ||||
|         // Store the "attempt".
 | ||||
|         await this.configProvider.set(this.READ_CHUNK_ATTEMPT_NAME, file.size); | ||||
| 
 | ||||
|         // Write the whole file.
 | ||||
|         const fileEntry = await this.fileProvider.writeFileDataInFileChunk(file, path, false); | ||||
| 
 | ||||
|         // Success, remove the attempt and increase the max chunk size if needed.
 | ||||
|         await this.configProvider.delete(this.READ_CHUNK_ATTEMPT_NAME); | ||||
| 
 | ||||
|         if (file.size > this.maxChunkSize) { | ||||
|             await this.storeMaxChunkSize(file.size + 1); | ||||
|         } | ||||
| 
 | ||||
|         return fileEntry; | ||||
|     } | ||||
| } | ||||
| 
 | ||||
| export class CoreFileHelper extends makeSingleton(CoreFileHelperProvider) {} | ||||
|  | ||||
| @ -65,7 +65,7 @@ export class CoreFileProvider { | ||||
|     static SITESFOLDER = 'sites'; | ||||
|     static TMPFOLDER = 'tmp'; | ||||
| 
 | ||||
|     static CHUNK_SIZE = 10485760; // 10 MB.
 | ||||
|     static CHUNK_SIZE = 1048576; // 1 MB. Same chunk size as Ionic Native.
 | ||||
| 
 | ||||
|     protected logger; | ||||
|     protected initialized = false; | ||||
| @ -639,6 +639,7 @@ export class CoreFileProvider { | ||||
|     /** | ||||
|      * Write some file data into a filesystem file. | ||||
|      * It's done in chunks to prevent crashing the app for big files. | ||||
|      * Please notice Ionic Native writeFile function already splits by chunks, but it doesn't have an onProgress function. | ||||
|      * | ||||
|      * @param file The data to write. | ||||
|      * @param path Path where to store the data. | ||||
| @ -646,19 +647,17 @@ export class CoreFileProvider { | ||||
|      * @param offset Offset where to start reading from. | ||||
|      * @param append Whether to append the data to the end of the file. | ||||
|      * @return Promise resolved when done. | ||||
|      * @deprecated since 3.8.3. Please use CoreFileHelperProvider.writeFileDataInFile instead. | ||||
|      */ | ||||
|     async writeFileDataInFile(file: Blob, path: string, onProgress?: CoreFileProgressFunction, offset: number = 0, | ||||
|             append?: boolean): Promise<FileEntry> { | ||||
| 
 | ||||
|         offset = offset || 0; | ||||
| 
 | ||||
|         // Get the chunk to read and write.
 | ||||
|         const readWholeFile = offset === 0 && CoreFileProvider.CHUNK_SIZE >= file.size; | ||||
|         const chunk = readWholeFile ? file : file.slice(offset, Math.min(offset + CoreFileProvider.CHUNK_SIZE, file.size)); | ||||
| 
 | ||||
|         try { | ||||
|             const fileEntry = await this.writeFileDataInFileChunk(chunk, path, append); | ||||
|             // Get the chunk to write.
 | ||||
|             const chunk = file.slice(offset, Math.min(offset + CoreFileProvider.CHUNK_SIZE, file.size)); | ||||
| 
 | ||||
|             const fileEntry = await this.writeFile(path, chunk, append); | ||||
| 
 | ||||
|             offset += CoreFileProvider.CHUNK_SIZE; | ||||
| 
 | ||||
| @ -676,32 +675,15 @@ export class CoreFileProvider { | ||||
|             // Read the next chunk.
 | ||||
|             return this.writeFileDataInFile(file, path, onProgress, offset, true); | ||||
|         } catch (error) { | ||||
|             if (readWholeFile || !error || error.name != 'NotReadableError') { | ||||
|                 return Promise.reject(error); | ||||
|             if (error && error.target && error.target.error) { | ||||
|                 // Error returned by the writer, get the "real" error.
 | ||||
|                 error = error.target.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); | ||||
|             throw error; | ||||
|         } | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Write a chunk of data into a file. | ||||
|      * | ||||
|      * @param chunkData The chunk of data. | ||||
|      * @param path Path where to store the data. | ||||
|      * @param append Whether to append the data to the end of the file. | ||||
|      * @return Promise resolved when done. | ||||
|      */ | ||||
|     writeFileDataInFileChunk(chunkData: Blob, path: string, append?: boolean): Promise<FileEntry> { | ||||
|         // Read the chunk data.
 | ||||
|         return this.readFileData(chunkData, CoreFileProvider.FORMATARRAYBUFFER).then((fileData) => { | ||||
|             // Write the data in the file.
 | ||||
|             return this.writeFile(path, fileData, append); | ||||
|         }); | ||||
|     } | ||||
| 
 | ||||
|     /** | ||||
|      * Gets a file that might be outside the app's folder. | ||||
|      * | ||||
|  | ||||
| @ -901,7 +901,7 @@ export class CoreWSProvider { | ||||
| 
 | ||||
|         return transfer.upload(filePath, uploadUrl, options, true).then((success) => { | ||||
|             const data = this.textUtils.parseJSON(success.response, null, | ||||
|                     this.logger.error.bind(this.logger, 'Error parsing response from upload')); | ||||
|                     this.logger.error.bind(this.logger, 'Error parsing response from upload', success.response)); | ||||
|             if (data === null) { | ||||
|                 return Promise.reject(this.translate.instant('core.errorinvalidresponse')); | ||||
|             } | ||||
|  | ||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user