GithubHelp home page GithubHelp logo

ackerapple / angular-file Goto Github PK

View Code? Open in Web Editor NEW

This project forked from valor-software/ng2-file-upload

128.0 9.0 40.0 56.1 MB

Angular components for user file select, drop, and more

Home Page: http://ackerapple.github.io/angular-file/

License: MIT License

JavaScript 100.00%

angular-file's Introduction

angular-file

Easy to use Angular directives for user file selections (DEMO PAGE)

hire me npm version npm downloads Dependency Status Build status Build Status min size minzip size

This package is to handle select/drag/drop of files. Once files are selected, for uploading, you then use Angular's @angular/common/http for uploading selected files (see here for more on uploading).

Table of Contents

Quick Start

  1. A recommended way to install angular-file is through npm package manager using the following command:

npm install angular-file --save-dev

Alternatively, you can download it in a ZIP file.

  1. Currently angular-file contains three directives: ngf, ngfSelect, and ngfDrop. ngf and ngfSelect are quite the same with just different defaults and they both utilize <input type="file" /> functionality. ngfDrop is used to designate an area that will be used for dropping of file(s).

  2. More information regarding using of angular-file is located in demo and demo sources.

Examples

Practical Example

An example intended to have every line needed to run an app with angular-file. To use this example, replace the contents of main.ts with this code, and add <app></app> to the body of index.html

import { ngfModule, ngf } from "angular-file"
import { Component, NgModule } from "@angular/core"
import {
  HttpClient, HttpClientModule, HttpRequest, HttpResponse, HttpEvent
} from "@angular/common/http"
import { platformBrowserDynamic } from "@angular/platform-browser-dynamic"
import { BrowserModule } from '@angular/platform-browser'
import { Subscription } from 'rxjs'

// two ways to upload files
const template = `
<input
  ngf
  multiple
  type      = "file"
  accept    = "image/*"
  [(files)] = "files"
  maxSize   = "1024"
  capturePaste = "1"
/>
<button *ngIf="files" (click)="uploadFiles(files)">send files</button>

<ngfFormData
  [files]      = "files"
  [(FormData)] = "myFormData"
  postName     = "file"
></ngfFormData>

<ngfUploadStatus
  [(percent)] = "uploadPercent"
  [httpEvent] = "httpEvent"
></ngfUploadStatus>

<div *ngIf="uploadPercent">
  Upload Progress: {{ uploadPercent }}%
</div>
`

@Component({
  selector: 'app',
  template: template
})
export class AppComponent {
  postUrl = '...'
  myFormData:FormData//populated by ngfFormData directive
  httpEvent:HttpEvent<{}>

  constructor(public HttpClient:HttpClient){}

  uploadFiles(files:File[]) : Subscription {
    const config = new HttpRequest('POST', this.postUrl, this.myFormData, {
      reportProgress: true
    })

    return this.HttpClient.request( config )
    .subscribe(event=>{
      this.httpEvent = event

      if (event instanceof HttpResponse) {
        alert('upload complete, old school alert used')
      }
    },
    error=>{
      alert('!failure beyond compare cause:' + error.toString())
    })
  }
}

@NgModule({
  imports: [
    BrowserModule,
    HttpClientModule,
    ngfModule
  ],
  declarations: [
    AppComponent
  ],
  bootstrap: [AppComponent]
})
export class AppModule {}

platformBrowserDynamic().bootstrapModule(AppModule);

Select Files Examples

Examples of how to allow file selection

Multiple

<input type="file" ngf [(files)]="files" multiple  />

Single

<input type="file" ngf [(file)]="file" />

Element

<div ngfSelect multiple="1" [(files)]="files">
  Tap to Select
</div>

Image Backgrounds Only

<button ngfSelect [(file)]="userFile" accept="image/*" multiple="1">
  Tap to Select
</button>
<div [ngfBackground]="userFile"
  style="background-size:cover;background-repeat:no-repeat;width:50px;height:50px"
></div>

Images Only

<button ngfSelect [(file)]="userFile" accept="image/*" multiple="1">
  Tap to Select
</button>
<img [ngfSrc]="userFile" />

Drop Files Examples

Examples of how to allow file drag/drop

Basic

<div ngfDrop
  [(files)]="files"
  [(file)]="file"
  ([validDrag])="validDrag"
  ([invalidDrag])="invalidDrag"
  [ngClass]="{'myHoverClass': validDrag, 'myAntiHoverClass': validDrag}"
>
  Drop Files Here
</div>

Combo Drop Select

<div ngfDrop selectable="1" multiple="1"
  [(files)]="files"
  [(validDrag)]="validComboDrag"
  [(invalidDrag)]="invalidComboDrag"
  [ngClass]="{'goodDragClass':validComboDrag, 'badDragClass':invalidComboDrag}"
>
  Combo drop/select zone
</div>

API

ngf Directive

A base directive that provides abilities of ngfDrop and ngfSelect. Does not auto default nor auto host element events like hover/drag/drop (see ngfDrop and/or ngfSelect)

ngf                 : ngf // reference to directive class
[multiple]          : string
[accept]            : string
[maxSize]           : number // bytes . 1024 = 1k . 1048576 = 1mb
[ngfFixOrientation] : boolean = true
[fileDropDisabled]  : any = false
[selectable]        : any = false
[(lastInvalids)]    : {file:File,type:string}[] = []
[(lastBaseUrl)]     : string // Base64 od last file uploaded url
[(file)]            : File // last file uploaded
[(files)]           : File[]
(init)              : EventEmitter<ngf>
[capturePaste]      : boolean // listen to window paste event for files
(fileSelectStart)   : EventEmitter<Event> // Event fired for user selecting files starting

ngfDrop Directive

Extends ngf and then auto hosts element event watching of hover/drag/drop

[fileDropDisabled]  : any = false
(fileOver)      :EventEmitter<any> = new EventEmitter()
[(validDrag)]   :any = false
[(invalidDrag)] :any = false

Supporting Internet Explorer 11 or less?

Only (fileOver) works accurately [(validDrag)] & [(invalidDrag)] should NOT be used as IE11 does not indicate the number of files NOR the types of files being dragged like other modern web browsers

ngfSelect Directive

Extends ngf and auto engages click base file selecting

[selectable]:any = true

ngfBackground Directive

[ngfBackground]:File

ngfSrc Directive

[ngfSrc]:File

ngfUploadStatus Directive

Does calculations of an upload event and provideds percent of upload completed

[(percent)]:number
[httpEvent]:Event

ngfFormData Directive

Converts files to FormData

[files]:File[]
[postName]:string = "file"
[fileName]:string//optional force file name
[(FormData)]:FormData

Uploading

Angular, natively, makes uploading files so very easy!

Did you know?

  • You do NOT and should NOT use a seperate package to upload files other than @angular/common
  • You do not need a package like ng2-file-upload which have outdated non-core-community driven file uploading scripts
  • Just can just use @angular/common to send files! Why add more unneccessary weight of dependency of another package?
  • Multi file uploading is so easy with @angular/common
  • You will have the most control seperating your file selecting from file uploading
  • You should use this package, angular-file, to select files and then give to Angular to upload

Uploading files is as easy as:

import { Subscription } from "rxjs"//only included for data typing
import {
  HttpClient, HttpRequest, HttpResponse
} from "@angular/common/http"

export const uploadFiles(files:File[]) : Subscription {
  const postUrl = "..."
  const myFormData:FormData = new FormData()

  files.forEach(file=>myFormData.append("file", file, "file-name.xyz"))

  const config = new HttpRequest("POST", postUrl, myFormData), {
    reportProgress: true
  })

  return this.HttpClient.request( config )
  .subscribe(event=>{
    if (event instanceof HttpResponse) {
      alert('upload complete, old school alert used')
    }
  },
  error=>{
    alert('!failure cause:' + error.toString())
  })
}

Troubleshooting

Please follow this guidelines when reporting bugs and feature requests:

  1. Use GitHub Issues board to report bugs and feature requests (not our email address)
  2. Please always write steps to reproduce the error. That way we can focus on fixing the bug, not scratching our heads trying to reproduce it.

Thanks for understanding!

Development

Work on this package

Source files are on not the default github branch

git clone https://github.com/AckerApple/angular-file.git -b development

Credits

  • Current Author: Acker Apple
  • Forked from outdated package: ng2-file-upload

License

The MIT License (see the LICENSE file for the full text)

angular-file's People

Contributors

ackerapple avatar bensgroi avatar buchslava avatar ciriarte avatar fojt avatar greenkeeperio-bot avatar hlaiveling avatar jpicornellhb avatar matthewdenobrega avatar mii9000 avatar rariancom avatar sylvaindumont avatar valorkin avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

angular-file's Issues

BUG: `ngfDrop` directive doesn't work with IE11

Drop a file on ngfDrop zone in IE11 and it will open in browser (default IE file drop action).

Can reproduce using demo site:
https://ackerapple.github.io/angular-file/

The original unforked ng2FileDrop directive still works fine with IE11 here:
https://valor-software.com/ng2-file-upload/

I did a small amount of debugging - it appears the drop event is handled by ngfDrop.onDrop() but files = [] here:

let files = this.eventToFiles(event)

if(!files.length)return

SE

Hi, I installed the package and my angular/core is 5.2.6. But after include the ngfModule into ngmodules, I got issue called "Can't resolve all parameters for ***" and if I removed this module, my app works fine. Is anyone have idea?

File Upload / upload completed

I am looking at the code and trying to see if this is already created or missing
and how to setup my code.

the uploader gets files added.
the user clicks the upload all files button

is there an event i can pickup that tells me all the files have finished uploading ?
i want to clear the queue and update my UI to show the files as uploaded to the server.

where to start ?

Type 'HttpEvent<{}>' is not assignable to type 'HttpEvent<Event>'.

I tried this but for me doesn't function

  postUrl = '(Api.getUrl(Api.URLS..........)';
  myFormData: FormData ;//populated by ngfFormData directive
  httpEvent: HttpEvent<Event>;

  uploadFiles(files:File[]) : Subscription {
    const config = new HttpRequest('POST', this.postUrl, this.myFormData), {
      reportProgress: true
    }) // exception [ts] Cannot redeclare block-scoped variable '(Missing)'.
    
    return this.HttpClient.request( config )
    .subscribe(event=>{
      this.httpEvent = event //exception Type 'HttpEvent<{}>' is not assignable to type 'HttpEvent<Event>'.
      
      if (event instanceof HttpResponse) {
        alert('upload complete, old school alert used')
      }
    },
    error=>{
      alert('!failure beyond compare cause:' + error.toString())
    })
  }

Extension ngfBackground for IMG tag and SRC attribute

What do you think to extend ngfBackground to apply data from input to "src" attribute if tag html is "IMG" ??

I've extended the sources to add one condition on ngfBackground directive.

@Directive({ selector: '[ngfBackground]' })
export class ngfBackground {
  @Input('ngfBackground') file: any

  constructor(public ElementRef: ElementRef) { }

  ngOnChanges(changes: any) {
    dataUrl(this.file)
      .then((src: any) => {
        
        if (this.ElementRef.nativeElement.tagName === "IMG") {
          this.ElementRef.nativeElement.src = src;
          return;
        }

        const urlString = 'url(\'' + (src || '') + '\')'
        this.ElementRef.nativeElement.style.backgroundImage = urlString
      })
  }
}

Ensure quality of unit tests

This project was a fork. The original project just barely had a unit test or two. Since then the unit tests have been upgraded heavily but still does not have enough code coverage.

Re-select same file Problem

If I selected a file and removed it from list by using splice function and try to re-select same file its not working. I also tested it on your live example page.

Service Example to receive files in FormData

As using FormData to send files to a server is relatively new to Angular2 and the new HttpClient, I'm finding it difficult to know how to best receive files on the server. Not being able to view the file data payload on the client side (other than interrogating the network payload itself) is making it difficult to write server side code.

An examples of server code implementing a simple receiver would make adopting this approach much more accessible.

Extension warning before size warning

When someone uploads an big file and also is not the accepted extension it should warn about that the filetype is invalid before it warns about the size is too big.

Otherwise the user would first shrink a file and then get's the news that his file type is not accepted

accept restriction file type not working

with out adding accept restriction, control is going to filesSelect() method in the below code and am able to the uploaded file. if I need to add restriction for file type its not working .

component.html file:
<span ngfSelect multiple="1" [(file)]="file" (fileChange)="filesSelect(file)" [accept] = "accept" >Browse

component.ts file:

accept = '.pdf, .jpg, .tif, .gif, .bmp, .jpeg'

Request: Share demo on StackBlitz

Hi

I found out that the source for demo is not available any more, as well as during implementation I found out some functionalities are not working as demo (by my mistakes). It would be beneficial if you could create stackblitz of the demo and share it in your readme file, then we could have fork it and do some tests to make sure if it's a bug or we missed something

Mac's .DS_Store in npm package

Hi,
I noticed that there is some litter in the npm package.
The .DS_store is completely useless there, even for Mac users ;)
I think it should be removed: just my 50 cent :)

Accepted ".xls" files are seen as invalid drag but gets in the array anyway

Hey, first of all thanks for taking the time to mantain this awesome project

My problem is, when I set accept to ".xls", wich translates to application/vnd.ms-excel mime type, drag and drop sees this as an invalid drag, wich shouldn't happen, but puts the file on the files array anyway. Can be reproduced on the demo page

upload-excel

No problem using the ngfSelect directive, the files is there for me to select it

(lastInvalidsChange) get invalid file

Hi,

So I have found out that there is an lastInvalidsChange event in the code (https://github.com/AckerApple/angular-file/blob/development/src/file-upload/ngf.directive.ts#L26).

using it like so: <div ngfDrop (lastInvalidsChange)="lastInvalidsChange(file,type)"></div>

Now when I try it out I neither get the invalid file as parameter and neither is the lastInvalids array updated.
using "angular-file": "^0.5.4",. and Angular 5

The only fix I was able to pull out was to wrap it around a setTimeout to get the updated array like so:

setTimeout(()=>{
  console.log("invalid files updated",this.lastInvalids);
},1);

Am I missing something? Or is my 'fix' atm the way to go?

Not allowing xls format for accepted files

Hi @AckerApple,

first of all, thanks for this awesome development! It's very very helpful :) but I'm facing an issue today, when trying to set the accept format file for xls files it doesn't work, maybe I'm doing something wrong or I'm using the wrong name, right now I'm doing:

accept = 'application/pdf, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet';

Thanks in advance for your help!

Unexpected value 'ngfModule' imported by the module 'LibraryModule'. Please add a @NgModule annotation.

I just attempted to import this into a new angular-cli project and got the following error. I attempted to add ngfModule to imports in the module consuming.

stateService.js:43 Error: Unexpected value 'ngfModule' imported by the module 'LibraryModule'. Please add a @NgModule annotation.
    at syntaxError (compiler.js:466)
    at eval (compiler.js:15088)
    at Array.forEach (<anonymous>)
    at CompileMetadataResolver.getNgModuleMetadata (compiler.js:15071)
    at JitCompiler._loadModules (compiler.js:33486)
    at JitCompiler._compileModuleAndComponents (compiler.js:33447)
    at JitCompiler.compileModuleAsync (compiler.js:33363)
    at CompilerImpl.compileModuleAsync (platform-browser-dynamic.js:230)
    at eval (core.js:6441)
    at ZoneDelegate.invoke (zone.js:392)

Cant get ngfFormData to update formdata

So I'm trying to replicate the example at: https://ackerapple.github.io/angular-file/

I had the uploadFiles() getting triggered from (filesChange), which seems like it fires to early to have done anything at all with the files collection.

I went ahead and set it up for manual triggering to upload to more closely match your example. SendableFormData is no longer undefined, but looks like an empty object. If I set a breakpoint in the upload click event, this.files contains one entry, sendableformdata is {}.

I was curious if you had any ideas there... and as soon as I get that resolved, I was wondering if there were events someplace I could subscribe to, that would let me get the sendableFormData at an appropriate time where its been updated.

Wrong maxSize

Hello,

maxSize parameter calculation is wrong :( this not kbyte, just byte

The error can also be simulated on the example page
image

thanks
eggp

Can't bind to 'files' since it isn't a known property of 'ngfFormData'

Hello,

I'm using a "Combo drop/select image" in my app.component.html.
I have added the 'ngfModule' in the imports section as you can see in my app.module.ts file.
After adding a ngfDrop item in my app.component.html, I have this error :

Can't bind to 'files' since it isn't a known property of 'ngfFormData'. ("<ngfFormData [ERROR ->][files]="files" postName="file" [(FormData)]="sendableFormData"></ngfFormData>

My app.module.ts

import { NgModule } from '@angular/core';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClientModule, HttpClient, HTTP_INTERCEPTORS } from "@angular/common/http";
import { FormsModule, ReactiveFormsModule } from "@angular/forms";
import { TranslateModule, TranslateLoader } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';

import { AppComponent } from './app.component';

import { ngfModule } from "angular-file";

@NgModule({
    declarations: [
        AppComponent
    ],
    imports: [
        BrowserModule,
        ngfModule,
        AppRoutingModule,
        HttpClientModule,
        BrowserAnimationsModule,
        FormsModule,
        ReactiveFormsModule,
    providers: [],
    bootstrap: [AppComponent]
})

export class AppModule {
}

My app.component.html

<ngfFormData [files]="files" postName="file" [(FormData)]="sendableFormData"></ngfFormData>

<ngfUploadStatus [(percent)]="progress" [httpEvent]="httpEvent"></ngfUploadStatus>

<div ngfDrop selectable="1" multiple="1" [(files)]="files" [(validDrag)]="validComboDrag" [(invalidDrag)]="invalidComboDrag" [ngClass]="{'goodDragClass':validComboDrag, 'badDragClass':invalidComboDrag}">
    Combo drop/select zone
</div>

Thanks

custom angular validator for ngfDrop [question]

Hi,

I am not very experienced in Angular, but as far as I understand it's possible to write validation (or add built in validation, like 'required') for this input:
<input type="file" ngf [(file)]="file" />

But is it possible to do the same for ngfDrop, like here:

<div ngfDrop
  [(files)]="files"
  [(file)]="file"
  ([validDrag])="validDrag"
  ([invalidDrag])="invalidDrag"
  [ngClass]="{'myHoverClass': validDrag, 'myAntiHoverClass': validDrag}"
>
  Drop Files Here
</div>

?

Security / Scenario Test - Manually changed extension are getting uploaded easily

Hi,

Thank you for this amazing library.

Recently i was testing a Security Scenario included by my lead.

What I do I want to upload only .XLSX type extension ( let's say 2 MB ). I go to folder and modify its file type manually to .png or .jpg.

I go to demo page and I upload this file in jpg format.

image

If my application is allowing to upload only valid image files, how do I make sure for above manually converted file type ( .xls to .jpg ) it throws an error and shows message like it is an invalid file. Right now it is uploading it without any issue.

Thank you.

Type of "CSV" files not recognize

Hi, nice work !

However, I think that some type of files are not recognize by angular-file (.db, .sql, .ttf, .csv, .log)
image
untitled

IMO, some mime types are missing... like "text/csv","application/csv","application/vnd.ms-excel","text/x-csv","application/x-csv"

Is your list not complete ? Or am I missing something ?

Simon

Dynamicallly setting [accept]

I am unable to bind the accept attribute ngfDrop. Here is my code

If the value of "accept" changes in the component, the directive is not updated.

Using with mutler-s3

Hi,

Thanks for forking this library, I was having so many issues with it.

I'm having trouble linking this up with multer-s3. This is probably me so bare with me.

I have an Angular/Node application that uses the ngfDirective to make calls to the backend where multer-s3 uploads the files to s3. Here is my current layout. Here is the error I am receiving:

Error: Unexpected field at makeError (/Users/XXX/Desktop/workspace/XXXX/node_modules/multer/lib/make-error.js:12:13)

My component.html file

   <div mat-dialog-title style="text-align: center">
      <!--<h6 *ngIf="filesUploaded" style="margin-bottom: 10px;">Click Create Item Below To List Item</h6>-->
      <h6 *ngIf="!filesUploaded" style="margin-bottom: 10px;">Click Camera to Add Photo For Sale or Rent</h6>
      <!--<h6 *ngIf="!filesUploaded" style="margin-bottom: 10px;">Add Another</h6>-->
    </div>
    <div mat-dialog-content style="text-align: center">
      <!--<div *ngFor="let item of uploader.queue">-->
        <!--<figure class="image-preview" style="margin: 0 auto;" *ngIf="!uploaderLoading">-->
          <!--<img class="is-64x64" src="" imgPreview [image]="item?._file" style="border-radius: 2%;">-->
        <!--</figure>-->
        <!--<p *ngIf="!uploaderLoading">{{ item?.file?.name }}</p>-->
      <!--</div>-->
      <mat-progress-bar mode="indeterminate" *ngIf="uploaderLoading" style="margin: 0 auto"></mat-progress-bar>
      <label for="file-input"><mat-icon *ngIf="!uploaderLoading" style="margin-bottom: 20px;">photo_camera</mat-icon></label>
      <ngfUploader
        [(ref)]     = "uploader"
        [options]   = "{url: devUrl,
                        itemAlias: 'photos'}"
        (save)      = "{}"
        (catch)     = "{}"
      ></ngfUploader>
      <input
        type="file"
        multiple
        class="file-input" 
        id="file-input"
        name="photo"
        accept="image/*"
        ngf
        style="display: none"
        (filesChange)="manualFormDataUploadFiles($event)"
      />
      <!--<input  type="file" name="photo" ngf [(files)]="files" [(file)]="file" multiple style="display: none">-->
    </div>
    <div mat-dialog-actions>
      <!--<button mat-raised-button color="primary" (click)="uploadFiles(files)" *ngIf="!filesUploaded && files" style="margin: 0 auto;" tabindex="2"><p class="p2">UPLOAD</p></button>-->
      <button mat-raised-button color="primary" (click)="sendByModel(file)" *ngIf="!filesUploaded && file" style="margin: 0 auto;" tabindex="2"><p class="p2">UPLOAD</p></button>

      <button mat-raised-button *ngIf="filesUploaded" color="primary" (click)="addItem()"><p class="p2">CREATE ITEM</p></button>
      <button mat-button (click)="onClose()"><p class="p2">CLOSE</p></button>
    </div>

My .ts file

export class UploaderDialogComponent implements OnInit {
  devUrl = 'XXX';
  url = 'XXX';
  filesUploaded = false;
  public uploader: ngfUploader;



  constructor(
    private http: Http,
    private userS: UserService,
    private contactS: ContactService,
    private router: Router,
    private uis: UiService,
    private itemS: ItemService,
    public dialogRef: MatDialogRef<UploaderDialogComponent>,
    @Inject(MAT_DIALOG_DATA) public data: any) { }

  ngOnInit() {
  }
// I tried all three
  uploadFiles(files: File[]):Promise<Response>{
    const uploader:FileUploader = this.uploader;

    const formData: FormData = uploader.getFormData(files);
    console.log(formData);

    const config = new Request({
      url: this.devUrl,
      method: 'POST',
      body: formData
    });

    return this.postRequest(config)
  }

  postRequest(config: Request):Promise<Response>{
    return this.http.request(config)
      .toPromise()
      .then( response => {
        alert('Upload Complete');
        return response;
      })
      .catch(e => this.uis.onFlash('ERROR POSTING IMAGE: ' + e.toString(), 'ERROR'));
  }

  sendByModel(file: File):Promise<Response>{
    const formData:FormData = this.uploader.getFormData( [file] );

    const config = new Request({
      url: this.devUrl,
      method:'POST',
      body: formData
    });
    return this.postRequest(config)
  }

  manualFormDataUploadFiles(files:File[]):Promise<Response>{
    const formData:FormData = new FormData();

    for (let file of files) {
      formData.append('file', file, file.name);
    }

    const config = new Request({
      url: this.devUrl,
      method:'POST',
      body:formData
    });

    return this.postRequest(config)
  }
}

And here is the backend code that raises the error

var express = require('express');
var router = express.Router();
var aws = require('aws-sdk');
var fs = require('fs');
var path = require('path');
var path3 = path.join(__dirname, "../config/config-aws.json");
var pdf = require('pdfkit');
var multer = require('multer');
var multerS3 = require('multer-s3');

aws.config.loadFromPath(path3);
var s3 = new aws.S3();
var fileName = '';
var uploadM = multer({
  storage: multerS3({
    s3: s3,
    bucket: 'XXX',
    acl: 'public-read',
    metadata: function (req, file, cb) {
      cb(null, {fieldName: file.fieldname});
    },
    key: function (req, file, cb) {
      fileName = Date.now().toString() + "-" + (Math.round(Math.random() * 100000)).toString() + '-' + file.originalname;
      cb(null, fileName)
    }
  })
});


router.post('/server/upload', uploadM.array('photos', 3), function(req,res) {
    if (res.error) {
      return res.status(400).json({
        message: "Error",
        error: res.error
      });
    }
    return res.status(200).send(fileName);

});


module.exports = router;

I've played around for a bit trying different methods and using itemAlias. With the outdated library I had it setup and working and I assumed I'd need to do some work to get multer-s3 up and running again.

Thanks, again for helping and creating this, it was much needed!

Consider removing ngFileUploader

I think we should remove and technologies that aide in transmitting files.

Issues this is causing:

  • People that don't know how to use HTML5 FormData, often come here thinking they need some heavy lifting file transmitter when they only need Angular+FormData
  • It is too costly to maintain an Http transmitter
  • The built-in file transmitter send multiple files as multiple single requests
  • It gets confusion trying to match input name attributes with FormData POST names. People that do not transmit as file name input "file", think the input name should be the FormData name. That's a stretch.

Does anyone wish to offer input on this subject matter before I get another issue report and rip out all the file transmitting parts of this library?

Null check missing on variable 'transfer'

eventToTransfer(event:any):any {
if(event.dataTransfer)return event.dataTransfer
return event.originalEvent ? event.originalEvent.dataTransfer : null
}

When event.dataTransfer or event.originalEvent.dataTransfer are undefined or null, function eventToTransfer returns null.
Then, there is no check if variable transfer is null or not in function eventToFiles. This leads to 'Cannot read property 'files' of null' error.

eventToFiles(event:Event){
const transfer = this.eventToTransfer(event);
if(transfer.files && transfer.files.length)return transfer.files
if(transfer.items && transfer.items.length)return transfer.items
return []
}

filesChange event emitter

Hi,
Thanks for the library, looks like you're making good progress with it.
I am wondering if you're going to add filesChange as a documented output for ngf directive?

Looking through the back issues and your comments, it appears to be a recent addition, in which case it simply may be the case that the documentation wasn't updated to reflect the new event emitter?

It is listed as an option in the upgrade section, but isn't listed as one of the available ngf attributes.

Mainly trying to figure out if this is going to be an officially supported option, or if it's only there for the upgraders.

Error while testing code

Hi,
I am trying to test your source code following these commands:
git clone https://github.com/AckerApple/angular-file.git
cd angular-file/
npm install
ng build

Then I got this error message:
ENOENT: no such file or directory, stat '/home/dummy/tmp/angular-file/test/tsconfig.json'
Error: ENOENT: no such file or directory, stat '/home/dummy/tmp/angular-file/test/tsconfig.json'

It shouldn't work out of the box? Should I do something else?
Thanks,

PS: Why .ts files are missing semicolons? For example:
demo/src/app/components/file-upload/simple-demo.component.ts

Support pipes separator in accept attribute

Hello,

bug: Linux Chrome Version 74.0.3729.157 (Official Build) (64-bit)
when add accept: text/plain, text/csv, application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, open system file upload panel, and selected custom file
image
types but i add pipe accept: text/plain|text/csv|application/vnd.openxmlformats-officedocument.spreadsheetml.sheet, open system file upload panel and good select file types,
image
but when select file, your validator send error :(


chrome file input accept property use pipe separator instead of comma separator

plugin use comma separator: https://github.com/AckerApple/angular-file/blob/development/src/file-upload/fileTools.ts#L8

--
I'm sorry, my English is pretty weak
by eggp

name="file" forced in the post method

Angular-file doesn't seem to care about the set name property of input.

On front side I have

<input type="file" ngf name="singleFile" (filesChange)="uploader.uploadFiles($event)" />
<ngfUploader [(ref)]="uploader" [options]="{url:'/upload'}"></ngfUploader>

and on the server side I have Multer trying to catch file with field "singleFile"

var upload = multer({ dest: 'tmp/' });
app.post('/upload', upload.single('singleFile'), function (req, res, next) { ... } );

It doesn't work even though the field names are matched. If I change

upload.single('singleFile')

to

upload.single('file')

it magically works!

Trying to send random.file and checking browser's console network tab I notice the post request has

Content-Disposition: form-data; name="file"; filename="random.file"
Content-Type: application/json

regardless what I type in name="singleFile" property.

Make FileUploader class stand alone

The Uploader class of ng-file-upload, for AngularJs, stood alone and this package will implement this same practice:
https://github.com/danialfarid/ng-file-upload#upload-service

Better to do sooner than later because a majority of people think a FileUploader class is a must. We won't remove FileUploader class as it has great value BUT it wont be mandatory nor defaulted in the directives.

  • Requires major version number change
  • Requires updating examples

"fileDropDisabled" option of "ngf" is not working for file drop.

If I set it to true, it disables, file selection, but not file drop.

I looked at source code and for me it seems that check is missing in ngfDrop event. I think it should be something like this:

  @HostListener('drop', ['$event'])
  onDrop(event:Event):void {
    this.closeDrags()
    // Condition below added:
    if (this.fileDropDisabled){
        return;
    }
    let files = this.eventToFiles(event)

    if(!files.length)return

    this.stopEvent(event);
    this.handleFiles(files)
  }

P.S. naming for this property seems to be not correct, or it should belong to ngfDrop rather than ngf.

Can't bind to 'files' since it's not a known property of ....

Here's the error I'm getting:

ERROR Error: Uncaught (in promise): Error: Template parse errors:
Can't bind to 'files' since it isn't a known property of 'ngfFormData'. ("
    <button *ngIf="files" (click)="uploadFiles(files)">send files</button>

    <ngfFormData [ERROR ->][files]="files" [(FormData)]="resume" postName="file"></ngfFormData>

    <ngfUploadStatus [(percent)"): ng:///ApplyModule/DetailsComponent.html@60:17
Can't bind to 'FormData' since it isn't a known property of 'ngfFormData'. ("on *ngIf="files" (click)="uploadFiles(files)">send files</button>

    <ngfFormData [files]="files" [ERROR ->][(FormData)]="resume" postName="file"></ngfFormData>

    <ngfUploadStatus [(percent)]="uploadPercent"): ng:///ApplyModule/DetailsComponent.html@60:33
'ngfFormData' is not a known element:
1. If 'ngfFormData' is an Angular component, then verify that it is part of this module.
2. To allow any element add 'NO_ERRORS_SCHEMA' to the '@NgModule.schemas' of this component. ("
    <button *ngIf="files" (click)="uploadFiles(files)">send files</button>

    [ERROR ->]<ngfFormData [files]="files" [(FormData)]="resume" postName="file"></ngfFormData>

I've pretty much copied and pasted from the project README.

app.module.ts:

import { NgModule } from '@angular/core';
import { RouterModule } from '@angular/router';
import { BrowserModule } from '@angular/platform-browser';
import { HttpClient, HttpClientModule } from '@angular/common/http';
import { BrowserAnimationsModule } from '@angular/platform-browser/animations';
import { TranslateLoader, TranslateModule } from '@ngx-translate/core';
import { TranslateHttpLoader } from '@ngx-translate/http-loader';

// import { Logger } from 'angular2-logger/core';

import { rootRouterConfig } from './app.routes';
import { AppCommonModule } from './components/common/app-common.module';
import { AppComponent } from './app.component';

import { RoutePartsService } from './services/route-parts/route-parts.service';
import { NavigationService } from './services/navigation/navigation.service';
import { AuthService } from './services/auth/auth.service';
import { AccountAPI, JobOpeningAPI } from './serverCalls';
import { ngfModule } from 'angular-file';

// AoT requires an exported function for factories
export function HttpLoaderFactory(http: HttpClient) {
  return new TranslateHttpLoader(http);
}

@NgModule({
  imports: [
    BrowserModule,
    BrowserAnimationsModule,
    HttpClientModule,
    AppCommonModule,
    ngfModule,
    TranslateModule.forRoot({
      loader: {
          provide: TranslateLoader,
          useFactory: HttpLoaderFactory,
          deps: [HttpClient]
      }
    }),
    RouterModule.forRoot(rootRouterConfig, { useHash: false })
  ],
  declarations: [ AppComponent ],
  providers: [
    RoutePartsService,
    NavigationService,
    AuthService,
    AccountAPI,
    JobOpeningAPI
    // Logger,
  ],
  bootstrap: [AppComponent]
})
export class AppModule { }

the component:

import { Component, OnInit } from '@angular/core';
// import { ActivatedRoute, Router } from '@angular/router';
import { HttpEvent } from '@angular/common/http';
import { MatButton } from '@angular/material';
import { FormControl, FormGroup, Validators } from '@angular/forms';
import { CustomValidators } from 'ng2-validation';
import { ngf, ngfModule } from 'angular-file';

// import { AccountAPI, JobOpeningAPI, SurveyApplyAPI } from '../../../serverCalls';
import { JobDetails, JobOpening, Survey, SurveyApply } from '../../../models';
// import { AuthService, SurveyService } from '../../../services';

@Component({
  selector: 'ngx-apply-details',
  templateUrl: './details.component.html',
  styleUrls: ['./details.component.scss']
})
export class DetailsComponent implements OnInit {
  public contactForm: FormGroup;
  public resumePostUrl: 'http://localhost:8080/api/v1/resume';
  public resume: FormData;
  public httpEvent: HttpEvent<Event>;

  private jobDetails: JobDetails;
  private jobOpening: JobOpening;

  constructor() {
    this.contactForm = new FormGroup({
      email: new FormControl('', [Validators.required, Validators.email]),
      firstName: new FormControl('', [Validators.required]),
      lastName: new FormControl('', [Validators.required]),
      phoneNumber: new FormControl('', [Validators.required, CustomValidators.phone('en-CA')])
    });
  }

  public ngOnInit(): void {
    this.jobDetails = JobDetails.initializeFromLocalStorage();
    this.jobOpening = this.jobDetails.jobOpenings[0];
  }

  public updateContactInformation(): void {
    console.log('yaaaaaaaaay');
  }
}

my html:

<mat-card>
  <mat-card-header>
    <mat-card-title>Upload New Resume &amp; Cover Letter</mat-card-title>
  </mat-card-header>
  <mat-card-content>
    <h3>Select files</h3>

    <input ngf multiple type="file" accept="image/*" [(files)]="files" maxSize="1024" />
    <button *ngIf="files" (click)="uploadFiles(files)">send files</button>

    <ngfFormData [files]="files" [(FormData)]="resume" postName="file"></ngfFormData>

    <ngfUploadStatus [(percent)]="uploadPercent" [httpEvent]="httpEvent"></ngfUploadStatus>

    <div *ngIf="uploadPercent">
      Upload Progress: {{ uploadPercent }}%
    </div>

  </mat-card-content>
</mat-card>

Bundlesize angular elements

After implementing the package size of the prod build went from 3660KB to 4202KB.

I dont understand why this happens as only the lib was added to the package lock.

Here are my dependencies:
: {
"@angular/animations": "^6.1.10",
"@angular/cdk": "^7.0.0",
"@angular/common": "^6.1.0",
"@angular/compiler": "^6.1.0",
"@angular/core": "^6.1.0",
"@angular/elements": "^6.1.10",
"@angular/forms": "^6.1.0",
"@angular/http": "^6.1.0",
"@angular/flex-layout": "^6.0.0-beta.16",
"@angular/material": "^7.0.0",
"@angular/material-moment-adapter": "^7.0.0",
"@angular/platform-browser": "^6.1.0",
"@angular/platform-browser-dynamic": "^6.1.0",
"@angular/router": "^6.1.0",
"@webcomponents/custom-elements": "^1.2.1",
"@webcomponents/webcomponentsjs": "^2.1.3",
"classlist.js": "^1.1.20150312",
"core-js": "^2.5.4",
"document-register-element": "^1.7.2",
"hammerjs": "^2.0.8",
"moment": "^2.22.2",
"rxjs": "^6.0.0",
"web-animations-js": "^2.3.1",
"zone.js": "~0.8.26"
}
would be amazing if u could help me out thanks :)

postName in ngfFormData for multiple files

Hi,

i'm trying to send more the 1 file to backend (PHP) with ngfDrop (multiple=1) but the server receives only 1 file ...

I solve replacing postName="file" with postName="file[]" in the relative ngfFormData.

Is it normal?

Limit number of files to upload

After checking the docs and readme, I have come to the conclusion that I cannot limit the number of uploads a user is allowed to upload through a directive.

I've implemented everything like in the demo, and have it working. I tried a few things through the component and template, but excess files are always remain in the queue. I checked through the src files and believe that in the ngfDrop directive it can be implemented. Specifically here (line 29 in link):

@HostListener('drop', ['$event'])
  onDrop(event:Event):void {
    this.closeDrags()
    let files = this.eventToFiles(event)

    if(!files.length || **files.length > MAX_FILES**) return;  **// ex. const MAX_FILES = 9;** 

    this.stopEvent(event);
    this.handleFiles(files)
  }

or even in ngf directive as an @input().

Finally, my question is, is there something I am missing or 'limiting number of files' not implemented? If not, can this feature be implemented?

Http and HttpClient : future path

just wanted to drop a note that i see that http is beeing replaced by HttpClient in the angular 4.3 / 4.4 releases.

ran into this last week when i was working on some code for Http Interception to pass JWT tokens to service calls.

the new HttpClient has the option of an Interceptor so that no added packages are needed.
but the old Http does not see the new Interecptor .

just wanted to make note of this and that we may at some point need to have two versions of the angular-file and or a need to document which Http is used and the effects of it.

Request: make "selectable" binding checked on changes

I think it would be a good idea to make the "selectable" input/prop bindable.

I'm making a feature and when there is a loader, I would set "selectable" to false until the loading finishes, I came to realize that the "selectable" input is being checked on ngOnInit, and because of it, it's not bindable.

I think every input or almost every input should be bindable for maximum flexbility.

Thanks for your time and mantaining this awesome library.

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    ๐Ÿ–– Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. ๐Ÿ“Š๐Ÿ“ˆ๐ŸŽ‰

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google โค๏ธ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.