Angular, File not uploaded to Firebase Storage - html

I'm trying to make an upload function for uploading file/image to my firebase database storage. I have already paste the correct API key in the environment.ts and import it to app.module.ts like AngularFireModule.initializeApp(environment.firebaseConfiguration, 'app-root'). I made the push string properties function and upload file function separately. The other properties like name and description are pushed correctly into my Firebase real-time database but the file is not uploaded to the storage so i also cant obtain the url.
//product.ts
export class Product {
$prdKey: string;
prdName: string;
prdImage ? : File;
imageURL ? : any;
prdDescription: string;
constructor(prdImage: File) {
this.prdImage = prdImage;
}
}
//product.service.ts
Product: any;
selectedProduct: Product = new Product(this.Product);
currentFileUpload: Product;
insertProduct(Product: Product) {
this.productList.push({
prdName: Product.prdName,
prdDescription: Product.prdDescription
});
}
private basePath = '/';
pushFileToStorage(Product: Product) {
const storageRef = firebase.storage().ref();
const uploadTask = storageRef.child(`${this.basePath}/${Product.prdImage.name}`).put(Product.prdImage);
uploadTask.on(firebase.storage.TaskEvent.STATE_CHANGED,
(snapshot) => {
// in progress
const snap = snapshot as firebase.storage.UploadTaskSnapshot
},
(error) => {
// fail
console.log(error)
},
() => {
// success
Product.imageURL = uploadTask.snapshot.downloadURL
Product.prdName = Product.prdImage.name
this.saveFileData(Product)
}
);
}
private saveFileData(Product: Product) {
this.firebase.list(`${this.basePath}/`).push(Product);
}
//product.component.ts
onSubmit(form: NgForm) {
if (form.value.$prdKey == null) {
this.ProductService.insertProduct(this.ProductService.selectedProduct);
} else {
this.ProductService.updateProduct(this.ProductService.selectedProduct);
}
}
upload() {
const file = this.ProductService.selectedProduct.prdImage
this.ProductService.currentFileUpload = new Product(file);
}
selectFile(event) {
this.ProductService.selectedProduct = event.target.files;
}
<!--product.component.html-->
<form #productForm="ngForm" (ngSubmit)="onSubmit(productForm); upload()">
<!--skip name and descrioption input-->
<label>Upload an Image</label>
<input type="file" class="form-control">
<button type="submit" class="btn btn-primary">Submit</button>
</form>
Can anyone help me solve this? Please let me know of more snippets are needed. Thank you in advance.

Related

Adonis controller doesn't store information to DB

I am writing a page where the user should put some information in two text areas, and this text data should write into DB. The row in DB creates with NULL in these two areas and DateTime is written there.
So in my database I have id|usuario_nombre|file_nombre|created_at| updated_at
and usuario_nombre|file_nombre have NULL, and others have information.
Can you help, please?
Controller :
'use strict'
const Upload = use('App/Models/Upload')
class UploadController {
async index({ view })
{
const uploads = await Upload.all();
return view.render('/', {
uploads: uploads.toJSON()
})
}
async create({ view })
{
return view.render('/upload');
}
async store({ request, response })
{
const upload = new Upload();
upload.usuario_nombre = request.input('usuario_nombre');
upload.file_nombre = request.input('profilefile');
upload.save();
response.redirect('/');
}
}
module.exports = UploadController
Form with inputs :
<form method="POST" enctype="multipart/form-data">
{{ csrfField() }}
<input type="text" id="usuario_nombre" name="usuario_nombre"/>
<input type="text" name="profilefile" id="profilefile"/>
<button type="submit"> Submit </button>
</form>
Routes :
Route.get('/upload/create', 'UploadController.create')
Route.get('/upload', 'UploadController.store')
Route.get('/upload/create', 'UploadController.create')
Route.get('/upload', 'UploadController.store')
Migration :
'use strict'
/** #type {import('#adonisjs/lucid/src/Schema')} */
const Schema = use('Schema')
class UploadsSchema extends Schema {
up() {
this.create('uploads', (table) => {
table.increments()
table.string('usuario_nombre')
table.string('file_nombre')
table.timestamps()
})
}
down() {
this.drop('uploads')
}
}
module.exports = UploadsSchema
Use await upload.save(); because save() is a async operation

HttpErrorResponse {headers: HttpHeaders, status: 415, statusText: "Unsupported Media Type"

Hi I tried to upload a csv file and convert it to json array and pass to the web api. But when I click the submit button I am getting this error. Anyone who can help to fix this?
Thank you :)
This is my .ts file in angular Here I tried to upload a csv file and convert it to json array.
changeListener(event: any) {
if (event.target.files.length > 0) {
const file = event.target.files[0];
this.myForm.patchValue({
fileSource: file
});
//File reader method
let reader: FileReader = new FileReader();
reader.readAsText(file);
reader.onload = (e) => {
let csv: any = reader.result;
let allTextLines = [];
allTextLines = csv.split(/\r|\n|\r/);
console.log('CSV: ', csv?.toString());
}
//JSON.stringify(file);
}
}
submit() {
const formData = new FormData();
formData.append('file', this.myForm.get('fileSource')?.value);
this.http.post('http://localhost:64233/api/employee', formData)
.subscribe(res => {
console.log(res);
alert('Upload Sussessful');
})
}
This is my .html file in angular
<form [formGroup]="myForm" (ngSubmit)="submit()">
<h1 style="text-align: center">File Upload</h1>
<br /><br />
<div class="form-group">
<label for="file">File</label>
<input class="form-control" formControlName="file" id="file" type="file" class="upload"
(change)="changeListener($event)" />
</div>
<button id="btnSave" class="btn btn-primary" type="submit">Submit</button>
</form>
This is the error I get when I click on submit button
I checked my web api in postman and it is working fine for json array. Really appreciate if you can help. Thank you
Ok I am talking to myself. But this is to help others.
Here in my .ts file, I have uploaded the file and read the data in the csv file as a string. But I have not converted it to json array correctly and push it to go to the web api.
So below is the working code. This may not be the perfect one but it works fine for me.
This is my .ts file in angular
export class FileUploadComponent implements OnInit {
myForm = new FormGroup({
file: new FormControl('', [Validators.required])
});
ngOnInit(): void {
this.resetForm();
}
constructor(private http: HttpClient, public fileUploadService: FileUploadService,
private toastr: ToastrService, private router: Router) { }
obj: any;
unique: any;
removeHeader: any;
// Maximum file size allowed to be uploaded = 1MB
maxSize: number = 1048576;
//upload file
fileUpload(event: any) {
if (event.target.files && event.target.files.length > 0) {
// Don't allow file sizes over 1MB
if (event.target.files[0].size < this.maxSize) {
const file = event.target.files[0];
console.log(file);
//File reader method
let reader: FileReader = new FileReader();
reader.readAsText(file);
reader.onload = (e) => {
let csv: any = reader.result;
let res: any[] = csv.split("\n");
//remove first element of the array
res.shift();
let jsonArray: any = [];
res.forEach(item => {
let singlePerson = item.split(",");
let singleObject = { employeeid: singlePerson[0], firstname: singlePerson[1], lastname: singlePerson[2], address: singlePerson[3] }
jsonArray.push(singleObject);
})
this.obj = jsonArray;
//check duplicates in csv file, remove, and return unique records
let unique = this.obj
.map((e: { [x: string]: any; }) => e['employeeid'])
.map((e: any, i: any, final: string | any[]) => final.indexOf(e) === i && i)
.filter((obje: string | number) => this.obj[obje])
.map((e: string | number) => this.obj[e]);
this.obj = unique;
}
}
else {
// Display error message
this.toastr.error("File is too large to upload");
}
}
}
resetForm() {
this.myForm.reset();
}
submit() {
this.fileUploadService.postFileUpload(this.obj);
this.resetForm();
}
}
This is my html file
<br /><br />
<form [formGroup]="myForm">
<h1 style="text-align: center">File Upload</h1>
<br /><br />
<div class="form-group">
<label for="file" style="font-size: 25px">File</label>
<input
class="form-control"
formControlName="file"
type="file"
accept=".csv"
class="upload"
(change)="fileUpload($event)"
/>
</div>
<div class="form-group">
<label> Please Upload a CSV or Text file of size less than 1MB </label>
</div>
<button class="btn btn-primary" type="submit" (click)="submit()">
Submit
</button>
</form>
This is my service class
export class FileUploadService {
messages: string[] = [];
constructor(private http: HttpClient, private toastr: ToastrService) { }
readonly baseURL = 'http://localhost:64233/api/employee';
myForm = new FormGroup({
file: new FormControl('', [Validators.required])
});
formData: FileUpload = new FileUpload();
//method for post request
postFileUpload(body: any) {
const requestOptions = { headers: new HttpHeaders({ 'content-type': "application/json" }) };
return this.http.post(this.baseURL, body, requestOptions)
.subscribe(
observer => {
this.toastr.success("File Uploaded Succesfully");
this.resetForm();
},
err => {
if (err.status == 500)
this.toastr.error("Empty File");
else
this.toastr.error("Please upload a file");
//console.log(err);
/* (error) => {
console.log(error); */
//throw new Error(error);
});
}
resetForm() {
this.myForm.reset();
this.formData = new FileUpload();
}
}
Here to display alerts I have used a toaster

Angular 6 file upload with form content

I have create a page with different input elements with file upload. While saving the form with multiple files along with form input elements using angular 6, the file object is empty {} in console an http service in network tab.
Here is my code:
onFileChanged(event) {
this.selectedFiles = event.target.files;
const uploadData = new FormData();
uploadData.append('myFile', this.selectedFiles, this.selectedFiles[0].name);
this.createFormData.attachment = uploadData;
};
Can anyone provide a sample to help me?
This is example of upload method in service. Pass files and input values from component to service, create formData, loop on files and append each file to formData and same with input values.
upload(files, inputs) {
let formData = new FormData();
files.map((file) => {
formData.append('file', file);
});
inputs.map((input) => {
formData.append(`${input.name}`, input.value);
});
return this.http.post(`some/api/upload`, formData)
.pipe(map((res) => res.data));
}
With this example your request should contain all array of files and inputs, also if you need some special header add it after formData in post method (in my case i handle headers in interceptor).
upload(files, inputs) {
let formData = new FormData();
files.map((file) => {
formData.append('file', file);
});
inputs.map((input) => {
formData.append(`${input.name}`, input.value);
});
const headers = new HttpHeaders({
'Accept': 'application/json'
});
const options = { headers: headers };
return this.http.post(`some/api/upload`, formData, options)
.pipe(map((res) => res.data));
}
Have a look at following example with npm's ng2-file-upload (in this case with a fontAwsome-icon).
myFileUploadForm.component.html:
<!-- file upload -->
<input #fileToUpload type="file" style="display:none;" ng2FileSelect (change)="onFileChanged($event)" [uploader]="uploader"
name="customerFile" id="customerFile" class="customerFile" />
<a href="javascript:document.getElementById('customerFile').click();">
<fa class="ql-upload" *ngIf="buttonDeaktivieren" [title]="'Upload'" [name]="'upload'" [size]="0.9" [border]=false></fa>
</a>
myFileUploadForm.component.ts (I'll ommit the obvious parts with ..):
import { Component, OnInit, ViewChild, OnDestroy, TemplateRef } from '#angular/core';
import { Subscription, Observable } from '../../../../../node_modules/rxjs';
....
...
import { FileUploader } from 'ng2-file-upload';
#Component({
....
...
..
})
export class myFileUploadFormComponent implements OnInit, OnDestroy {
public uploader: FileUploader = new FileUploader({ url:
'http://localhost:3000/files/uploadFile/', itemAlias: 'customerFile' });
filesArray = [];
constructor(
...
..
private http: Http
) { }
ngOnInit() {
....
...
..
}
// INFO: Function for opening confirm modal when deleting file
openDeleteFileModal(file) {
const initialState = {
file: file
};
this.deleteFileModalRef = this.modalService.show(ConfirmFileDeletionComponent, {
initialState, class: 'modal-md modal-dialog-centered' });
}
// INFO: Handy helper for assigning appropriate file-icon according to extension
getFilesIcon(file) {
if (file === 'docx') {
return 'file-word-o';
} else if (file === 'jpeg' || file === 'jpg' || file === 'png') {
return 'image';
} else if (file === 'pdf') {
return 'file-pdf-o';
} else if (file === 'xlsx' || file === 'xls') {
return 'file-excel-o';
} else if (file === 'pptx') {
return 'file-powerpoint-o';
} else if (file === 'zip') {
return 'file-archive-o';
} else {
return 'file';
}
}
/* INFO : service for downloading the uploaded file */
downloadFile(filename) {
this.fileDataService.downloadFile(filename);
}
onFileChanged(event) {
this.uploader.onBuildItemForm = (fileItem: any, form: any) => {
form.append('id', this.customer.id);
form.append('customername', this.customer.customername);
};
this.uploader.uploadAll();
}
ngOnDestroy() {
this.subscription.unsubscribe();
}
}
Obviously this is my implementation suited to my needs (uploaded files are related to a certain customer and are displayed with icons according to extension and listed for future download or deletion as well), but I'm sure you can get it done by adjusting the code to your needs and write the relevant services. Have a nice one weekend ;)

output data from json file in React

I need to output data from the json file that the user loads at the front.
I download the json file, but I get a strange store in Redux and can not figure out how to further display the data to the screen from the store.
What should I need to do?
import React from 'react'
import { connect } from 'react-redux'
import * as actions from './actions'
class File extends React.Component {
constructor (props) {
super(props)
}
handleChange (e) {
e.preventDefault();
let reader = new FileReader();
let file = e.target.files[0];
reader.onloadend = () => {
let text = reader.result;
this.props.jsonLoad(JSON.parse(text))
}
reader.readAsText(file)
}
render () {
return (
<div>
<h3> Add your file: </h3>
<input type="file" multiple onChange={this.handleChange.bind(this)}/>
<button >
add text from file
</button>
</div>
)
}
}
const mapStateToProps = (state) => {
return {
json: state.json
}
}
function mapDispatchToProps (dispatch) {
return {
jsonLoad: (json) => dispatch(actions.jsonLoad(json)),
}
}
export default connect(mapStateToProps, mapDispatchToProps)(File)
action.js
const USER_JSON = 'USER_JSON';
export function jsonLoad(json) {
console.log( json)
return function (dispatch) {
let file = json
dispatch(addFile(file))
}
}
export function addFile (json) {
return{
type: 'USER_JSON',
payload: json
}
};

TypeError: Cannot read property 'File' of undefined

I want to upload file to my firebase storage and have the url stored in database. I followed an example that i found on this link. I have two different ts classes. I got an error in my pushFileToStorage function that said TypeError: Cannot read property 'file' of undefined when i hit the submit button. Can anyone help me solve this please?.
//these are from two different class files
//fileUpload.ts
export class FileUpload {
name: string;
Url: string;
File: File;
constructor(prdFile: File) {
this.prdFile = prdFile;
}
}
//product.ts
export class Product {
$prdKey: string;
prdName: string;
prdImage: string;
prdDescription: string;
}
//product.service.ts
basePath = '/Product';
pushFileToStorage(fileUpload: FileUpload, Product: Product, progress: {
percentage: number
}) {
const storageRef = firebase.storage().ref();
const uploadTask = storageRef.child(`${this.basePath}/${fileUpload.File.name}`).put(fileUpload.File);
uploadTask.on(firebase.storage.TaskEvent.STATE_CHANGED,
(snapshot) => {
// in progress
const snap = snapshot as firebase.storage.UploadTaskSnapshot
progress.percentage = Math.round((snap.bytesTransferred / snap.totalBytes) * 100)
},
(error) => {
// fail
console.log(error)
},
() => {
// success
this.productList.push({
prdName: Product.prdName,
prdImage: Product.prdImage = fileUpload.Url = uploadTask.snapshot.downloadURL,
prdDescription: Product.prdDescription,
})
this.saveFileData(fileUpload)
}
);
}
private saveFileData(fileUpload: FileUpload) {
this.firebase.list(`${this.basePath}/`).push(fileUpload);
}
//product.component.ts
currentFileUpload: FileUpload;
onSubmit(form: NgForm) {
this.ProductService.pushFileToStorage(this.currentFileUpload, this.ProductService.selectedProduct, this.progress);
}
When you do currentFileUpload: FileUpload; you are not providing any value for it, you are only providing the type for currentFileUpload. The value will still be undefined. To initialize set it to an instance:
currentFileUpload: FileUpload = fileUploadInstance; // Get the instance somehow