forked from CIT/Vmeda.Online
		
	MOBILE-3401 file: Fix selecting files for offline with chooser
This commit is contained in:
		
							parent
							
								
									68b963638a
								
							
						
					
					
						commit
						4da6a31168
					
				| @ -74,7 +74,7 @@ export class CoreFileUploaderFileHandler implements CoreFileUploaderHandler { | |||||||
| 
 | 
 | ||||||
|         if (this.appProvider.isMobile()) { |         if (this.appProvider.isMobile()) { | ||||||
|             handler.action = (maxSize?: number, upload?: boolean, allowOffline?: boolean, mimetypes?: string[]): Promise<any> => { |             handler.action = (maxSize?: number, upload?: boolean, allowOffline?: boolean, mimetypes?: string[]): Promise<any> => { | ||||||
|                 return this.uploaderHelper.chooseAndUploadFile(maxSize, upload, mimetypes).then((result) => { |                 return this.uploaderHelper.chooseAndUploadFile(maxSize, upload, allowOffline, mimetypes).then((result) => { | ||||||
|                     return { |                     return { | ||||||
|                         treated: true, |                         treated: true, | ||||||
|                         result: result |                         result: result | ||||||
|  | |||||||
| @ -60,9 +60,10 @@ export class CoreFileUploaderHelperProvider { | |||||||
|      * @param maxSize Max size of the upload. -1 for no max size. |      * @param maxSize Max size of the upload. -1 for no max size. | ||||||
|      * @param upload True if the file should be uploaded, false to return the picked file. |      * @param upload True if the file should be uploaded, false to return the picked file. | ||||||
|      * @param mimetypes List of supported mimetypes. If undefined, all mimetypes supported. |      * @param mimetypes List of supported mimetypes. If undefined, all mimetypes supported. | ||||||
|  |      * @param allowOffline True to allow uploading in offline. | ||||||
|      * @return Promise resolved when done. |      * @return Promise resolved when done. | ||||||
|      */ |      */ | ||||||
|     async chooseAndUploadFile(maxSize: number, upload?: boolean, mimetypes?: string[]): Promise<any> { |     async chooseAndUploadFile(maxSize: number, upload?: boolean, allowOffline?: boolean, mimetypes?: string[]): Promise<any> { | ||||||
| 
 | 
 | ||||||
|         const result = await this.fileChooser.getFile(mimetypes ? mimetypes.join(',') : undefined); |         const result = await this.fileChooser.getFile(mimetypes ? mimetypes.join(',') : undefined); | ||||||
| 
 | 
 | ||||||
| @ -76,9 +77,28 @@ export class CoreFileUploaderHelperProvider { | |||||||
|             result.name = this.getChosenFileNameFromPath(result) || result.name; |             result.name = this.getChosenFileNameFromPath(result) || result.name; | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         const options = this.fileUploaderProvider.getFileUploadOptions(result.uri, result.name, result.mediaType, true); |         // Verify that the mimetype is supported.
 | ||||||
|  |         const error = this.fileUploaderProvider.isInvalidMimetype(mimetypes, result.name, result.mediaType); | ||||||
| 
 | 
 | ||||||
|         return this.uploadFile(result.uri, maxSize, true, options); |         if (error) { | ||||||
|  |             return Promise.reject(error); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         if (upload) { | ||||||
|  |             const size = await this.fileProvider.getExternalFileSize(result.uri); | ||||||
|  | 
 | ||||||
|  |             await this.confirmUploadFile(size, false, allowOffline); | ||||||
|  | 
 | ||||||
|  |             const options = this.fileUploaderProvider.getFileUploadOptions(result.uri, result.name, result.mediaType, true); | ||||||
|  | 
 | ||||||
|  |             return this.uploadFile(result.uri, maxSize, true, options); | ||||||
|  |         } else { | ||||||
|  |             const entry = await this.fileProvider.getExternalFile(result.uri); | ||||||
|  | 
 | ||||||
|  |             entry.name = result.name; // In Android sometimes the file is exported with a different name, use the original one.
 | ||||||
|  | 
 | ||||||
|  |             return entry; | ||||||
|  |         } | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -664,15 +684,17 @@ export class CoreFileUploaderHelperProvider { | |||||||
|      * @param name Name to use when uploading the file. If not defined, use the file's name. |      * @param name Name to use when uploading the file. If not defined, use the file's name. | ||||||
|      * @return Promise resolved when done. |      * @return Promise resolved when done. | ||||||
|      */ |      */ | ||||||
|     uploadFileObject(file: any, maxSize?: number, upload?: boolean, allowOffline?: boolean, name?: string): Promise<any> { |     async uploadFileObject(file: any, maxSize?: number, upload?: boolean, allowOffline?: boolean, name?: string): Promise<any> { | ||||||
|         if (maxSize != -1 && file.size > maxSize) { |         if (maxSize != -1 && file.size > maxSize) { | ||||||
|             return this.errorMaxBytes(maxSize, file.name); |             return this.errorMaxBytes(maxSize, file.name); | ||||||
|         } |         } | ||||||
| 
 | 
 | ||||||
|         return this.confirmUploadFile(file.size, false, allowOffline).then(() => { |         if (upload) { | ||||||
|             // We have the data of the file to be uploaded, but not its URL (needed). Create a copy of the file to upload it.
 |             await this.confirmUploadFile(file.size, false, allowOffline); | ||||||
|             return this.copyAndUploadFile(file, upload, name); |         } | ||||||
|         }); | 
 | ||||||
|  |         // We have the data of the file to be uploaded, but not its URL (needed). Create a copy of the file to upload it.
 | ||||||
|  |         return this.copyAndUploadFile(file, upload, name); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|  | |||||||
| @ -696,6 +696,18 @@ export class CoreFileProvider { | |||||||
|         }); |         }); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|  |     /** | ||||||
|  |      * Calculate the size of a file. | ||||||
|  |      * | ||||||
|  |      * @param path Absolute path to the file. | ||||||
|  |      * @return Promise to be resolved when the size is calculated. | ||||||
|  |      */ | ||||||
|  |     async getExternalFileSize(path: string): Promise<number> { | ||||||
|  |         const fileEntry = await this.getExternalFile(path); | ||||||
|  | 
 | ||||||
|  |         return this.getSize(fileEntry); | ||||||
|  |     } | ||||||
|  | 
 | ||||||
|     /** |     /** | ||||||
|      * Removes a file that might be outside the app's folder. |      * Removes a file that might be outside the app's folder. | ||||||
|      * |      * | ||||||
| @ -770,7 +782,7 @@ export class CoreFileProvider { | |||||||
|      * @return Promise resolved when the entry is moved. |      * @return Promise resolved when the entry is moved. | ||||||
|      */ |      */ | ||||||
|     moveDir(originalPath: string, newPath: string, destDirExists?: boolean): Promise<any> { |     moveDir(originalPath: string, newPath: string, destDirExists?: boolean): Promise<any> { | ||||||
|         return this.moveFileOrDir(originalPath, newPath, true, destDirExists); |         return this.copyOrMoveFileOrDir(originalPath, newPath, true, false, destDirExists); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -783,47 +795,7 @@ export class CoreFileProvider { | |||||||
|      * @return Promise resolved when the entry is moved. |      * @return Promise resolved when the entry is moved. | ||||||
|      */ |      */ | ||||||
|     moveFile(originalPath: string, newPath: string, destDirExists?: boolean): Promise<any> { |     moveFile(originalPath: string, newPath: string, destDirExists?: boolean): Promise<any> { | ||||||
|         return this.moveFileOrDir(originalPath, newPath, false, destDirExists); |         return this.copyOrMoveFileOrDir(originalPath, newPath, false, false, destDirExists); | ||||||
|     } |  | ||||||
| 
 |  | ||||||
|     /** |  | ||||||
|      * Move a file/dir. |  | ||||||
|      * |  | ||||||
|      * @param originalPath Path to the file/dir to move. |  | ||||||
|      * @param newPath New path of the file/dir. |  | ||||||
|      * @param isDir Whether it's a dir or a file. |  | ||||||
|      * @param destDirExists Set it to true if you know the directory where to put the file/dir exists. If false, the function will |  | ||||||
|      *                      try to create it (slower). |  | ||||||
|      * @return Promise resolved when the entry is moved. |  | ||||||
|      */ |  | ||||||
|     protected moveFileOrDir(originalPath: string, newPath: string, isDir?: boolean, destDirExists?: boolean): Promise<any> { |  | ||||||
|         const moveFn = isDir ? this.file.moveDir.bind(this.file) : this.file.moveFile.bind(this.file); |  | ||||||
| 
 |  | ||||||
|         return this.init().then(() => { |  | ||||||
|             // Remove basePath if it's in the paths.
 |  | ||||||
|             originalPath = this.removeStartingSlash(originalPath.replace(this.basePath, '')); |  | ||||||
|             newPath = this.removeStartingSlash(newPath.replace(this.basePath, '')); |  | ||||||
| 
 |  | ||||||
|             const newPathFileAndDir = this.getFileAndDirectoryFromPath(newPath); |  | ||||||
| 
 |  | ||||||
|             if (newPathFileAndDir.directory && !destDirExists) { |  | ||||||
|                 // Create the target directory if it doesn't exist.
 |  | ||||||
|                 return this.createDir(newPathFileAndDir.directory); |  | ||||||
|             } |  | ||||||
|         }).then(() => { |  | ||||||
| 
 |  | ||||||
|             return moveFn(this.basePath, originalPath, this.basePath, newPath).catch((error) => { |  | ||||||
|                 // The move can fail if the path has encoded characters. Try again if that's the case.
 |  | ||||||
|                 const decodedOriginal = decodeURI(originalPath), |  | ||||||
|                     decodedNew = decodeURI(newPath); |  | ||||||
| 
 |  | ||||||
|                 if (decodedOriginal != originalPath || decodedNew != newPath) { |  | ||||||
|                     return moveFn(this.basePath, decodedOriginal, this.basePath, decodedNew); |  | ||||||
|                 } else { |  | ||||||
|                     return Promise.reject(error); |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
|         }); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -836,7 +808,7 @@ export class CoreFileProvider { | |||||||
|      * @return Promise resolved when the entry is copied. |      * @return Promise resolved when the entry is copied. | ||||||
|      */ |      */ | ||||||
|     copyDir(from: string, to: string, destDirExists?: boolean): Promise<any> { |     copyDir(from: string, to: string, destDirExists?: boolean): Promise<any> { | ||||||
|         return this.copyFileOrDir(from, to, true, destDirExists); |         return this.copyOrMoveFileOrDir(from, to, true, true, destDirExists); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -849,46 +821,61 @@ export class CoreFileProvider { | |||||||
|      * @return Promise resolved when the entry is copied. |      * @return Promise resolved when the entry is copied. | ||||||
|      */ |      */ | ||||||
|     copyFile(from: string, to: string, destDirExists?: boolean): Promise<any> { |     copyFile(from: string, to: string, destDirExists?: boolean): Promise<any> { | ||||||
|         return this.copyFileOrDir(from, to, false, destDirExists); |         return this.copyOrMoveFileOrDir(from, to, false, true, destDirExists); | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
|      * Copy a file or a directory. |      * Copy or move a file or a directory. | ||||||
|      * |      * | ||||||
|      * @param from Path to the file/dir to move. |      * @param from Path to the file/dir to move. | ||||||
|      * @param to New path of the file/dir. |      * @param to New path of the file/dir. | ||||||
|      * @param isDir Whether it's a dir or a file. |      * @param isDir Whether it's a dir or a file. | ||||||
|  |      * @param copy Whether to copy. If false, it will move the file. | ||||||
|      * @param destDirExists Set it to true if you know the directory where to put the file/dir exists. If false, the function will |      * @param destDirExists Set it to true if you know the directory where to put the file/dir exists. If false, the function will | ||||||
|      *                      try to create it (slower). |      *                      try to create it (slower). | ||||||
|      * @return Promise resolved when the entry is copied. |      * @return Promise resolved when the entry is copied. | ||||||
|      */ |      */ | ||||||
|     protected copyFileOrDir(from: string, to: string, isDir?: boolean, destDirExists?: boolean): Promise<any> { |     protected async copyOrMoveFileOrDir(from: string, to: string, isDir?: boolean, copy?: boolean, destDirExists?: boolean) | ||||||
|         const copyFn = isDir ? this.file.copyDir.bind(this.file) : this.file.copyFile.bind(this.file); |             : Promise<Entry> { | ||||||
| 
 | 
 | ||||||
|         return this.init().then(() => { |         const fileIsInAppFolder = this.isPathInAppFolder(from); | ||||||
|             // Paths cannot start with "/". Remove basePath if present.
 |  | ||||||
|             from = this.removeStartingSlash(from.replace(this.basePath, '')); |  | ||||||
|             to = this.removeStartingSlash(to.replace(this.basePath, '')); |  | ||||||
| 
 | 
 | ||||||
|             const toFileAndDir = this.getFileAndDirectoryFromPath(to); |         if (!fileIsInAppFolder) { | ||||||
|  |             return this.copyOrMoveExternalFile(from, to, copy); | ||||||
|  |         } | ||||||
| 
 | 
 | ||||||
|             if (toFileAndDir.directory && !destDirExists) { |         const moveCopyFn = copy ? | ||||||
|                 // Create the target directory if it doesn't exist.
 |                 (isDir ? this.file.copyDir.bind(this.file) : this.file.copyFile.bind(this.file)) : | ||||||
|                 return this.createDir(toFileAndDir.directory); |                 (isDir ? this.file.moveDir.bind(this.file) : this.file.moveFile.bind(this.file)); | ||||||
|  | 
 | ||||||
|  |         await this.init(); | ||||||
|  | 
 | ||||||
|  |         // Paths cannot start with "/". Remove basePath if present.
 | ||||||
|  |         from = this.removeStartingSlash(from.replace(this.basePath, '')); | ||||||
|  |         to = this.removeStartingSlash(to.replace(this.basePath, '')); | ||||||
|  | 
 | ||||||
|  |         const toFileAndDir = this.getFileAndDirectoryFromPath(to); | ||||||
|  | 
 | ||||||
|  |         if (toFileAndDir.directory && !destDirExists) { | ||||||
|  |             // Create the target directory if it doesn't exist.
 | ||||||
|  |             await this.createDir(toFileAndDir.directory); | ||||||
|  |         } | ||||||
|  | 
 | ||||||
|  |         try { | ||||||
|  |             const entry = await moveCopyFn(this.basePath, from, this.basePath, to); | ||||||
|  | 
 | ||||||
|  |             return entry; | ||||||
|  |         } catch (error) { | ||||||
|  |             // The copy can fail if the path has encoded characters. Try again if that's the case.
 | ||||||
|  |             const decodedFrom = decodeURI(from); | ||||||
|  |             const decodedTo = decodeURI(to); | ||||||
|  | 
 | ||||||
|  |             if (from != decodedFrom || to != decodedTo) { | ||||||
|  |                 return moveCopyFn(this.basePath, decodedFrom, this.basePath, decodedTo); | ||||||
|  |             } else { | ||||||
|  |                 return Promise.reject(error); | ||||||
|             } |             } | ||||||
|         }).then(() => { |         } | ||||||
|             return copyFn(this.basePath, from, this.basePath, to).catch((error) => { |  | ||||||
|                 // The copy can fail if the path has encoded characters. Try again if that's the case.
 |  | ||||||
|                 const decodedFrom = decodeURI(from), |  | ||||||
|                     decodedTo = decodeURI(to); |  | ||||||
| 
 |  | ||||||
|                 if (from != decodedFrom || to != decodedTo) { |  | ||||||
|                     return copyFn(this.basePath, decodedFrom, this.basePath, decodedTo); |  | ||||||
|                 } else { |  | ||||||
|                     return Promise.reject(error); |  | ||||||
|                 } |  | ||||||
|             }); |  | ||||||
|         }); |  | ||||||
|     } |     } | ||||||
| 
 | 
 | ||||||
|     /** |     /** | ||||||
| @ -1281,6 +1268,16 @@ export class CoreFileProvider { | |||||||
| 
 | 
 | ||||||
|         return src.replace(CoreConfigConstants.ioswebviewscheme + '://localhost/_app_file_', 'file://'); |         return src.replace(CoreConfigConstants.ioswebviewscheme + '://localhost/_app_file_', 'file://'); | ||||||
|     } |     } | ||||||
|  | 
 | ||||||
|  |     /** | ||||||
|  |      * Check if a certain path is in the app's folder (basePath). | ||||||
|  |      * | ||||||
|  |      * @param path Path to check. | ||||||
|  |      * @return Whether it's in the app folder. | ||||||
|  |      */ | ||||||
|  |     protected isPathInAppFolder(path: string): boolean { | ||||||
|  |         return !path || !path.match(/^[a-z0-9]+:\/\//i) || path.indexOf(this.basePath) != -1; | ||||||
|  |     } | ||||||
| } | } | ||||||
| 
 | 
 | ||||||
| export class CoreFile extends makeSingleton(CoreFileProvider) {} | export class CoreFile extends makeSingleton(CoreFileProvider) {} | ||||||
|  | |||||||
		Loading…
	
	
			
			x
			
			
		
	
		Reference in New Issue
	
	Block a user