Как заставить средство выбора входного файла HTML указать исходное имя файла в Ionic (Android)?

Я использую HTML input для выбора файла в моем приложении Ionic3/Angular. Я использую код ниже:

// в файле .html

<input #fileUpload type="file" name="myfile"(change)="onFileChoose($event)"/>

// в файле .ts

onFileChoose($event): void {
    this.fileChooser.getFileInfo($event).then((result) => {
      this.fileName = result.fileName;
      this.fileData = this.sanitizeFileData(result.fileData);
      this.fileSize = result.fileSize;
      this.fileType = result.fileType;
    }, (error) => {
      this.helperProvider.createAlert('Alert', 'File is corrupted.');
    });
  }

 getFileInfo(event: Event): Promise<any> {

    let target = event && event.target;
    let files: Array<File> = target && target['files'];

    console.log(files[0].type);
    console.log(files[0].name);

    return new Promise((resolve, reject) => {
      if (files && files.length) {
        files = Array.from(files);
        let fileName = files[0].name;
        let fileSize = files[0].size;
        let fileType = files[0].type;
        let fileReader = new FileReader();

        fileReader.onload = () => resolve({
          fileData: fileReader.result,
          fileName: fileName,
          fileSize: fileSize,
          fileType: fileType
        });

        fileReader.onerror = error => reject(error);

        fileReader.onabort = error => reject(error);

        fileReader.readAsDataURL(files[0])
      }
    });
  }

Это отлично работает в iOS и Browser. Как в Android, так и в браузере я мог получить исходное имя, размер и тип файла. Но проблема возникает в Android.

Сценарий-1 (Android): когда я выбираю файл изображения с помощью средства выбора файлов, я могу получить исходное имя файла, размер и тип файла.

Сценарий 2 (Android). Когда я выбираю файл, отличный от файла изображения, например .pdf, .doc и т. д., я не могу получить оригинальное имя файла и тип файла. Предположим, я выбрал имя файла "sample.pdf", но после того, как я выбрал файл, я получаю имя файла в виде случайного числа, например 45675 и самое главное, тип файла, который я получил, пустой.

Затем я исследовал stackoverflow и увидел эти ссылки (link1 и ссылка2). Это может быть проблемой безопасности для Android.

Существует библиотека ionic-native/file-chooser, но она предназначена только для < strong>платформа Android.

Есть ли способ заставить Android указать исходное имя файла?


person Setu Kumar Basak    schedule 08.04.2018    source источник


Ответы (1)


Android не дает исходное имя файла и тип файла, используя мой подход, описанный выше, и это проблема безопасности для Android. Итак, мне пришлось сделать следующее решение для получения правильного имени файла, типа файла, размера файла и данных файла в base64.

Вам понадобятся следующие четыре плагина:

  1. FileChooser
  2. Файл
  3. Путь к файлу
  4. Base64

FileChooserAndroidProvider:

import {Injectable} from '@angular/core';
import {File, FileEntry, IFile} from "@ionic-native/file";
import {Base64} from "@ionic-native/base64";
import {FilePath} from "@ionic-native/file-path";
import {FileChooser} from "@ionic-native/file-chooser";


@Injectable()
export class FileChooserAndroidProvider {

  constructor(private base64: Base64, private filePath: FilePath, private file: File, private fileChooser: FileChooser) {
  }

  getFileInfo(): Promise<any> {
    return this.fileChooser.open().then((fileURI) => {
      return this.filePath.resolveNativePath(fileURI).then((filePath) => {
        return this.file.resolveLocalFilesystemUrl(filePath).then((fileEntry: FileEntry) => {
          return new Promise((resolve, reject) => {
            fileEntry.file(meta => resolve(meta), error => reject(error));
          });
        }).then((fileMeta: IFile) => {
          return new Promise((resolve, reject) => {
            return this.base64.encodeFile(filePath).then((base64Data) => {
              resolve({
                fileData: base64Data,
                fileName: fileMeta.name,
                fileSize: fileMeta.size,
                fileType: fileMeta.type
              })
            }).catch((error) => {
              reject(error);
            })
          })
        });
      });
    });
  }
}

FileChooserAndroidProviderModule:

import {NgModule} from '@angular/core';
import {Base64} from "@ionic-native/base64";
import {FileChooser} from "@ionic-native/file-chooser";
import {FilePath} from "@ionic-native/file-path";
import {File} from "@ionic-native/file";

@NgModule({
  declarations: [],
  exports: [],
  providers: [
    FileChooser,
    File,
    FilePath,
    Base64
  ]
})
export class FileChooserAndroidProviderModule {
}

Образец страницы:

constructor(private fileChooserAndroid: FileChooserAndroidProvider){}

  uploadFileForAndroid(): void {
    this.fileChooserAndroid.getFileInfo().then((result) => {
      this.fileName = result.fileName;
      this.fileData = this.sanitizeFileData(result.fileData);
      this.fileSize = result.fileSize;
      this.fileType = result.fileType;
    }).catch((error) => {
      this.helperProvider.createAlert('Alert', 'File can not be uploaded.');
    });
  }

SamplePageModule:

@NgModule({
  declarations: [
    SamplePage
  ],
  imports: [
    FileChooserAndroidProviderModule
  ],
  providers: [
    FileChooserAndroidProvider
  ]
})
export class SamplePageModule {
}
person Setu Kumar Basak    schedule 12.04.2018