Created
November 1, 2016 10:18
-
-
Save stalniy/5bc1d59bdb69a605ff6ebef036729abb to your computer and use it in GitHub Desktop.
Ionic/Cordova file upload
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Inject } from 'lib/angular2' | |
import { File, Transfer } from 'ionic-native' | |
import { Events } from 'events' | |
import { Config } from 'config/env' | |
@Inject(Events, Config) | |
export class CordovaUploadTransport { | |
get cacheDirectory() { | |
return cordova.file.tempDirectory || cordova.file.cacheDirectory | |
} | |
constructor(events, config) { | |
this.events = events | |
this.defaultUrl = `${config.get('API_URL')}/files` | |
} | |
upload(file, options) { | |
return this._upload(file, options) | |
.then(uploadResult => JSON.parse(uploadResult.response)) | |
.catch(uploadError => { | |
const response = this.parseError(uploadError) | |
this.events.publish('data:request:error', response) | |
return Promise.reject(response) | |
}) | |
} | |
_upload(file, options) { | |
return this.createTmpFileFrom(file).then(fileEntry => { | |
const params = Object.assign({ headers: {}, chunkedMode: true }, options) | |
if (params.url) { | |
delete params.url | |
} | |
this.events.publish('data:request', params) | |
return this._uploadAndRemoveFile(fileEntry, options.url || this.defaultUrl, params) | |
}).catch(err => { | |
console.log(err) | |
return Promise.reject(err) | |
}) | |
} | |
_uploadAndRemoveFile(fileEntry, url, params) { | |
const uploadRequest = new Transfer().upload(fileEntry.toURL(), url, params) | |
const removeFile = File.remove.bind(null, fileEntry) | |
uploadRequest.then(removeFile, removeFile) | |
return uploadRequest | |
} | |
createTmpFileFrom(file) { | |
// TODO: use File.writeFile when passing options to `File.getFile` is fixed in ionic-native | |
return File.resolveDirectoryUrl(this.cacheDirectory) | |
.then(fse => File.getFile(fse, `${Date.now()}.${file.name}`, { create: true })) | |
.then(fe => this.writeFile(fe, file)) | |
} | |
writeFile(fe, file) { | |
return File.createWriter(fe) | |
.then(writer => File.write(writer, file)) | |
.then(() => fe) | |
} | |
parseError(response) { | |
const uploadResponse = JSON.parse(response.body) | |
return { | |
status: uploadResponse.statusCode, | |
message: uploadResponse.message, | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
<ion-card> | |
<label class="file-upload"> | |
<ion-spinner name="ios-small" [hidden]="!isUploading"></ion-spinner> | |
<ion-icon name="add" [hidden]="isUploading"> Add</ion-icon> | |
<input type="file" (change)="uploadFiles($event.target.files)" #fileInput [attr.accept]="accept" /> | |
</label> | |
</ion-card> |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import { Component, Input, Output, Renderer, ViewChild, EventEmitter } from '@angular/core' | |
import { Inject } from 'lib/angular2' | |
import template from './file-upload.html' | |
import './file-upload.scss' | |
export class FileUploadTransport { | |
upload() { | |
throw new Error('Upload transport is not specified.') | |
} | |
} | |
@Inject(FileUploadTransport, Renderer) | |
@Component({ | |
template, | |
selector: 'file-upload', | |
exportAs: 'uploader', | |
}) | |
export class FileUpload { | |
isMultiple = false | |
@Input() | |
set multiple(value) { | |
this.isMultiple = value === '' || Boolean(value) | |
} | |
@Input() accept = '*/*' | |
@Output() uploaded = new EventEmitter() | |
@Output() uploadError = new EventEmitter() | |
@ViewChild('fileInput') fileInput = null | |
constructor(transport, renderer, zone) { | |
this.transport = transport | |
this.renderer = renderer | |
this.zone = zone | |
} | |
ngAfterViewInit() { | |
if (this.isMultiple) { | |
this.renderer.setElementAttribute(this.fileInput.nativeElement, 'multiple', 'multiple') | |
} | |
} | |
uploadFiles(filesList) { | |
const files = Array.prototype.slice.call(filesList, 0) | |
const requests = files.map(this.uploadFile, this) | |
const finishUploading = () => this.isUploading = false | |
this.isUploading = true | |
return Promise.all(requests) | |
.then(finishUploading, finishUploading) | |
} | |
uploadFile(file) { | |
return this.transport.upload(file, this.fileToOptions(file)) | |
.then(remoteFile => this.uploaded.emit(remoteFile)) | |
.catch(e => this.uploadError.emit(e)) | |
} | |
fileToOptions(file) { | |
return { | |
fileKey: 'file', | |
fileName: file.name, | |
mimeType: file.type, | |
} | |
} | |
} |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
@import 'variables'; | |
file-upload { | |
width: 68px; | |
height: 68px; | |
margin: 5px; | |
ion-card { | |
width: 100%; | |
height: 100%; | |
margin: 0; | |
overflow: hidden; | |
border-style: dashed; | |
border-width: 2px; | |
} | |
.file-upload { | |
position: relative; | |
display: flex; | |
align-items: center; | |
height: 100%; | |
width: 100%; | |
input { | |
position: absolute; | |
top: -1000px; | |
left: -1000px; | |
opacity: 0; | |
} | |
ion-icon, ion-spinner { | |
margin: 0 auto; | |
font-family: inherit; | |
} | |
} | |
&:hover, &:active { | |
ion-card { | |
border-color: color($colors, primary); | |
color: color($colors, primary); | |
} | |
} | |
&:active { | |
ion-icon { | |
margin-top: 5px; | |
} | |
} | |
} |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment