首页 文章

Ionic 2从浏览器上传文件

提问于
浏览
3

我有一个Ionic 2 PWA,所以它应该在浏览器中运行 . 我希望用户可以将文件上传到服务器 . 因为来自离子原生的文件选择器仅用于android,我不能在浏览器中使用它 . 所以我的想法是使用type =“file”的输入字段 . 但我的问题是,我只获取文件名而不是路径 . 要上传文件,我需要路径 . 起初我用ngModel尝试了它,然后用离子的表单构建器 . 这是我的表单生成器代码:

TS:

import {Component} from '@angular/core';
import {Validators, FormBuilder, FormGroup } from '@angular/forms';

@Component({
    selector: 'page-test',
    templateUrl: 'test.html',
})
export class TestPage {

    private file : FormGroup;

    constructor( private formBuilder: FormBuilder ) {
        this.file = this.formBuilder.group({
            image: ['']
        });
    }

    logForm(){
        console.log(this.file.value)
    }

}

HTML:

...
<ion-content padding>
    <form [formGroup]="file" (ngSubmit)="logForm()">
        <input type="file" size="50" formControlName="image">
        <button ion-button type="submit">Submit</button>
    </form>
</ion-content>

但就像我说的,控制台只记录文件名:

对象{image:“2970.jpg”}

如果我记录“this.file”(没有.value),我发现既没有文件对象,也没有这样的东西 . 有没有办法在离子浏览器应用程序中获取文件路径以将其上载到服务器?

1 回答

  • 2

    我不知道你是否已经找到了解决方案,但无论如何我都会发布它...

    对于此解决方案,您不需要任何外部npm模块 . 这是一步一步的

    通过运行创建新组件

    $ ionic generate component file-uploader
    

    然后复制并粘贴下面的代码

    src/components/file-uploader/file-uploader.ts

    import { Component, ViewChild, ElementRef, Input } from '@angular/core';
    
    import 'rxjs/add/operator/map';
    import { Observable } from 'rxjs/Observable';
    import { HttpClient } from '@angular/common/http';
    
    /**
     * Usage
     *
     *  <file-uploader [apiUrl]="apiUrl" [params]="uploadParams"></file-uploader>
     *
     *  <file-uploader [apiUrl]="apiUrl" [params]="[{'key':'language_code', 'value': 'en'}]"></file-uploader>
     *
     */
    
    @Component({
    selector: 'file-uploader',
    templateUrl: 'file-uploader.html'
    })
    export class FileUploaderComponent
    {
        @ViewChild('file') fileInput: ElementRef;
    
        @Input('apiUrl') apiUrl: string = null;
    
        @Input('params') params: Array<{key: string, value: string}> = [];
    
        @Input('buttonText') buttonText: string = 'Upload';
    
        @Input('buttonType') buttonType: 'button' | 'icon' = 'icon';
    
        @Input('icon') icon: string = 'cloud-upload';
    
        @Input('onUploadSuccess') onUploadSuccess: (file: File, response: any) => void
            = function (file: File, response: any) { console.log(file); console.log(response); };
    
        @Input('onUploadError') onUploadError: (file: File) => void = function (error: any) { console.log(error) };
    
        fileToUpload: File = null;
    
        constructor(private httpClient: HttpClient)
        {
        }
    
        triggerFileInputClick()
        {
            this.fileInput.nativeElement.click();
        }
    
        onFileInputChange(files: FileList)
        {
            this.fileToUpload = files.item(0);
    
            if (this.fileInput.nativeElement.value != '')
            {
                this.upload();
            }
        }
    
        upload()
        {
            const formData: FormData = new FormData();
    
            formData.append('file', this.fileToUpload, this.fileToUpload.name);
    
            this.params.map(param => {
                formData.append(param.key, param.value);
            });
    
            let headers = {};
    
            this.httpClient
                .post(this.apiUrl, formData, { headers: headers })
                // .map(() => { return true; })
                .subscribe(response => {
                    this.onUploadSuccess(this.fileToUpload, response);
    
                    this.fileInput.nativeElement.value = '';
                }, error => {
                    this.onUploadError(error);
                });
        }
    }
    

    src/components/file-uploader/file-uploader.html

    <div>
    
        <input type="file" #file (change)="onFileInputChange($event.target.files)">
    
        <button *ngIf="buttonType == 'button'" ion-button (click)="triggerFileInputClick()">{{buttonText}}</button>
    
        <ion-icon *ngIf="buttonType == 'icon'" name="cloud-upload" (click)="triggerFileInputClick()"></ion-icon>
    
    </div>
    

    src/components/file-uploader/file-uploader.scss

    file-uploader {
        [type=file] {
            display: none;
        }
    }
    

    src/pages/home/home.html

    <file-uploader [apiUrl]="apiUrl" [params]="[{'key':'language_code', 'value': languageCode}]"></file-uploader>
    

    您现在需要做的就是在NgModule中加载组件并使用它 .

    我要提到的最后一件事是,如果您遇到未定义属性的问题,例如apiUrl,你应该在ngOnInit()方法中初始化它们 .

    希望有所帮助

    UPDATE 唐't forget to import file uploader into the component that is using uploader or else you' ll得到 Can't bind to 'apiUrl' since it isn't a known property of 'file-uploader' 错误 . 我所做的是在components文件夹中创建了新模块components.module.ts文件 . 然后我将文件上传器组件导入其中 . 为了使用它,我将组件模块导入到使用文件上传器组件的组件中 .

    src/components/components.module.ts

    import { IonicModule } from 'ionic-angular';
    import { NgModule } from '@angular/core';
    import { FileUploaderComponent } from './file-uploader/file-uploader';
    
    @NgModule({
        declarations: [
            FileUploaderComponent
        ],
        imports: [
            IonicModule,
        ],
        exports: [
            FileUploaderComponent
        ]
    })
    export class ComponentsModule {}
    

    src/pages/home/home.module.ts

    import { ComponentsModule } from '../../components/components.module';
    

相关问题