我是Angular的初学者,我想知道如何创建Angular 5文件上传部分,我试图找到任何教程或文档,但我在任何地方都看不到任何东西。对此有什么想法吗?我尝试了ng4-files,但它不适用于Angular 5
当前回答
就我个人而言,我使用ngx-material-file-input作为前端,Firebase作为后端。更准确地说,后端是与Cloud Firestore结合的Cloud Storage for Firebase。下面是一个示例,它限制文件不大于20 MB,并且只接受某些文件扩展名。我还使用Cloud Firestore来存储上传文件的链接,但你可以跳过这个。
contact.component.html
<mat-form-field>
<!--
Accept only files in the following format: .doc, .docx, .jpg, .jpeg, .pdf, .png, .xls, .xlsx. However, this is easy to bypass, Cloud Storage rules has been set up on the back-end side.
-->
<ngx-mat-file-input
[accept]="[
'.doc',
'.docx',
'.jpg',
'.jpeg',
'.pdf',
'.png',
'.xls',
'.xlsx'
]"
(change)="uploadFile($event)"
formControlName="fileUploader"
multiple
aria-label="Here you can add additional files about your project, which can be helpeful for us."
placeholder="Additional files"
title="Additional files"
type="file"
>
</ngx-mat-file-input>
<mat-icon matSuffix>folder</mat-icon>
<mat-hint
>Accepted formats: DOC, DOCX, JPG, JPEG, PDF, PNG, XLS and XLSX,
maximum files upload size: 20 MB.
</mat-hint>
<!--
Non-null assertion operators are required to let know the compiler that this value is not empty and exists.
-->
<mat-error
*ngIf="contactForm.get('fileUploader')!.hasError('maxContentSize')"
>
This size is too large,
<strong
>maximum acceptable upload size is
{{
contactForm.get('fileUploader')?.getError('maxContentSize')
.maxSize | byteFormat
}}</strong
>
(uploaded size:
{{
contactForm.get('fileUploader')?.getError('maxContentSize')
.actualSize | byteFormat
}}).
</mat-error>
</mat-form-field>
ts(大小验证器部分)
import { FileValidator } from 'ngx-material-file-input';
import { FormBuilder, FormGroup, Validators } from '@angular/forms';
/**
* @constructor
* @description Creates a new instance of this component.
* @param {formBuilder} - an abstraction class object to create a form group control for the contact form.
*/
constructor(
private angularFirestore: AngularFirestore,
private angularFireStorage: AngularFireStorage,
private formBuilder: FormBuilder
) {}
public maxFileSize = 20971520;
public contactForm: FormGroup = this.formBuilder.group({
fileUploader: [
'',
Validators.compose([
FileValidator.maxContentSize(this.maxFileSize),
Validators.maxLength(512),
Validators.minLength(2)
])
]
})
ts(文件上传器部分)
import { AngularFirestore } from '@angular/fire/firestore';
import {
AngularFireStorage,
AngularFireStorageReference,
AngularFireUploadTask
} from '@angular/fire/storage';
import { catchError, finalize } from 'rxjs/operators';
import { throwError } from 'rxjs';
public downloadURL: string[] = [];
/**
* @description Upload additional files to Cloud Firestore and get URL to the files.
* @param {event} - object of sent files.
* @returns {void}
*/
public uploadFile(event: any): void {
// Iterate through all uploaded files.
for (let i = 0; i < event.target.files.length; i++) {
const randomId = Math.random()
.toString(36)
.substring(2); // Create random ID, so the same file names can be uploaded to Cloud Firestore.
const file = event.target.files[i]; // Get each uploaded file.
// Get file reference.
const fileRef: AngularFireStorageReference = this.angularFireStorage.ref(
randomId
);
// Create upload task.
const task: AngularFireUploadTask = this.angularFireStorage.upload(
randomId,
file
);
// Upload file to Cloud Firestore.
task
.snapshotChanges()
.pipe(
finalize(() => {
fileRef.getDownloadURL().subscribe((downloadURL: string) => {
this.angularFirestore
.collection(process.env.FIRESTORE_COLLECTION_FILES!) // Non-null assertion operator is required to let know the compiler that this value is not empty and exists.
.add({ downloadURL: downloadURL });
this.downloadURL.push(downloadURL);
});
}),
catchError((error: any) => {
return throwError(error);
})
)
.subscribe();
}
}
storage.rules
rules_version = '2';
service firebase.storage {
match /b/{bucket}/o {
match /{allPaths=**} {
allow read; // Required in order to send this as attachment.
// Allow write files Firebase Storage, only if:
// 1) File is no more than 20MB
// 2) Content type is in one of the following formats: .doc, .docx, .jpg, .jpeg, .pdf, .png, .xls, .xlsx.
allow write: if request.resource.size <= 20 * 1024 * 1024
&& (request.resource.contentType.matches('application/msword')
|| request.resource.contentType.matches('application/vnd.openxmlformats-officedocument.wordprocessingml.document')
|| request.resource.contentType.matches('image/jpg')
|| request.resource.contentType.matches('image/jpeg')
|| request.resource.contentType.matches('application/pdf')
|| request.resource.contentType.matches('image/png')
|| request.resource.contentType.matches('application/vnd.ms-excel')
|| request.resource.contentType.matches('application/vnd.openxmlformats-officedocument.spreadsheetml.sheet'))
}
}
}
其他回答
好的,因为这个线程出现在谷歌的第一个结果中,对于其他有同样问题的用户,你不需要像trueboroda指出的那样重新开始,有ng2-file-upload库,它简化了使用angular 6和7上传文件的过程,你所需要做的是:
安装最新的Angular CLI
yarn add global @angular/cli
出于兼容性考虑,请安装rx-compat
npm install rxjs-compat --save
安装ng2-file-upload
npm install ng2-file-upload --save
在你的模块中导入FileSelectDirective指令。
import { FileSelectDirective } from 'ng2-file-upload';
Add it to [declarations] under @NgModule:
declarations: [ ... FileSelectDirective , ... ]
在你的组件中
import { FileUploader } from 'ng2-file-upload/ng2-file-upload';
...
export class AppComponent implements OnInit {
public uploader: FileUploader = new FileUploader({url: URL, itemAlias: 'photo'});
}
模板
<input type="file" name="photo" ng2FileSelect [uploader]="uploader" />
为了更好地理解,你可以查看这个链接: 如何使用Angular 6/7上传文件
非常简单和最快的方法是使用ng2-file-upload。
通过npm安装ng2-file-upload。NPM I ng2-file-upload——保存
首先在模块中导入模块。
import { FileUploadModule } from 'ng2-file-upload';
Add it to [imports] under @NgModule:
imports: [ ... FileUploadModule, ... ]
标记:
<input ng2FileSelect type="file" accept=".xml" [uploader]="uploader"/>
在你的组件中:
import { FileUploader } from 'ng2-file-upload';
...
uploader: FileUploader = new FileUploader({ url: "api/your_upload", removeAfterUpload: false, autoUpload: true });
这是最简单的用法。要知道所有的权力,这看到演示
在我的情况下,我使用http拦截器,事情是,默认情况下,我的http拦截器设置内容类型头为应用程序/json,但对于文件上传,我使用multer库。 稍微改变一下我的http。interceptor定义,如果请求体是FormData,它会删除头,不触及访问令牌。 下面是一部分代码,它让我很开心。
if (request.body instanceof FormData) {
request = request.clone({ headers: request.headers.delete('Content-Type', 'application/json') });
}
if (request.body instanceof FormData) {
request = request.clone({ headers: request.headers.delete('Accept', 'application/json')});
}
通过这种方式,我实现了在项目中上传文件到web API。
我为谁分担关心。
const formData: FormData = new FormData();
formData.append('Image', image, image.name);
formData.append('ComponentId', componentId);
return this.http.post('/api/dashboard/UploadImage', formData);
一步一步
ASP。网上广告
[HttpPost]
[Route("api/dashboard/UploadImage")]
public HttpResponseMessage UploadImage()
{
string imageName = null;
var httpRequest = HttpContext.Current.Request;
//Upload Image
var postedFile = httpRequest.Files["Image"];
//Create custom filename
if (postedFile != null)
{
imageName = new String(Path.GetFileNameWithoutExtension(postedFile.FileName).Take(10).ToArray()).Replace(" ", "-");
imageName = imageName + DateTime.Now.ToString("yymmssfff") + Path.GetExtension(postedFile.FileName);
var filePath = HttpContext.Current.Server.MapPath("~/Images/" + imageName);
postedFile.SaveAs(filePath);
}
}
HTML表单
<form #imageForm=ngForm (ngSubmit)="OnSubmit(Image)">
<img [src]="imageUrl" class="imgArea">
<div class="image-upload">
<label for="file-input">
<img src="upload.jpg" />
</label>
<input id="file-input" #Image type="file" (change)="handleFileInput($event.target.files)" />
<button type="submit" class="btn-large btn-submit" [disabled]="Image.value=='' || !imageForm.valid"><i
class="material-icons">save</i></button>
</div>
</form>
TS文件使用API
OnSubmit(Image) {
this.dashboardService.uploadImage(this.componentId, this.fileToUpload).subscribe(
data => {
console.log('done');
Image.value = null;
this.imageUrl = "/assets/img/logo.png";
}
);
}
服务TS
uploadImage(componentId, image) {
const formData: FormData = new FormData();
formData.append('Image', image, image.name);
formData.append('ComponentId', componentId);
return this.http.post('/api/dashboard/UploadImage', formData);
}
下面是我上传excel文件的方法: 目录结构:
app
|-----uploadcomponent
|-----uploadcomponent.module.ts
|-----uploadcomponent.html
|-----app.module.ts
|-----app.component.ts
|-----app.service.ts
uploadcomponent.html
<div>
<form [formGroup]="form" (ngSubmit)="onSubmit()">
<input type="file" name="profile" enctype="multipart/form-data" accept=".xlsm,application/msexcel" (change)="onChange($event)" />
<button type="submit">Upload Template</button>
<button id="delete_button" class="delete_button" type="reset"><i class="fa fa-trash"></i></button>
</form>
</div>
uploadcomponent.ts
import { FormBuilder, FormGroup, ReactiveFormsModule } from '@angular/forms';
import { Component, OnInit } from '@angular/core';
....
export class UploadComponent implements OnInit {
form: FormGroup;
constructor(private formBuilder: FormBuilder, private uploadService: AppService) {}
ngOnInit() {
this.form = this.formBuilder.group({
profile: ['']
});
}
onChange(event) {
if (event.target.files.length > 0) {
const file = event.target.files[0];
this.form.get('profile').setValue(file);
console.log(this.form.get('profile').value)
}
}
onSubmit() {
const formData = new FormData();
formData.append('file', this.form.get('profile').value);
this.uploadService.upload(formData).subscribe(
(res) => {
this.response = res;
console.log(res);
},
(err) => {
console.log(err);
});
}
}
app.service.ts
upload(formData) {
const endpoint = this.service_url+'upload/';
const httpOptions = headers: new HttpHeaders({ <<<< Changes are here
'Authorization': 'token xxxxxxx'})
};
return this.http.post(endpoint, formData, httpOptions);
}
在后台,我使用DJango REST框架。 models.py
from __future__ import unicode_literals
from django.db import models
from django.db import connection
from django_mysql.models import JSONField, Model
import uuid
import os
def change_filename(instance, filename):
extension = filename.split('.')[-1]
file_name = os.path.splitext(filename)[0]
uuid_name = uuid.uuid4()
return file_name+"_"+str(uuid_name)+"."+extension
class UploadTemplate (Model):
id = models.AutoField(primary_key=True)
file = models.FileField(blank=False, null=False, upload_to=change_filename)
def __str__(self):
return str(self.file.name)
views.py。
class UploadView(APIView):
serializer_class = UploadSerializer
parser_classes = [MultiPartParser]
def get_queryset(self):
queryset = UploadTemplate.objects.all()
return queryset
def post(self, request, *args, **kwargs):
file_serializer = UploadSerializer(data=request.data)
status = None
message = None
if file_serializer.is_valid():
file_serializer.save()
status = "Success"
message = "Success"
else:
status = "Failure"
message = "Failure!"
content = {'status': status, 'message': message}
return Response(content)
serializers.py。
from uploadtemplate.models import UploadTemplate
from rest_framework import serializers
class UploadSerializer(serializers.ModelSerializer):
class Meta:
model = UploadTemplate
fields = '__all__'
urls . py。
router.register(r'uploadtemplate', uploadtemplateviews.UploadTemplateView,
base_name='UploadTemplate')
urlpatterns = [
....
url(r'upload/', uploadtemplateviews.UploadTemplateView.as_view()),
] + static(settings.STATIC_URL, document_root=settings.STATIC_ROOT)
if settings.DEBUG:
urlpatterns += static(settings.MEDIA_URL, document_root=settings.MEDIA_ROOT)
MEDIA_URL和MEDIA_ROOT在项目的settings.py中定义。
谢谢!
推荐文章
- Angular 5 -复制到剪贴板
- 错误:在switch上没有指定name属性的窗体控件的值访问器
- TypeScript枚举对象数组
- Angular 2 - innerHTML样式
- Angular 2显示和隐藏一个元素
- 具有构造签名的接口如何工作?
- 'React'指的是一个UMD全局,但当前文件是一个模块
- Angular 2中的“component”不是一个已知的元素
- TypeScript错误:属性“X”在类型“Window”上不存在
- 我怎么能计算在打字稿2日期之间的时间
- 如何刷新一个数据源(mat-table)
- 正确使用错误
- 如何修复TS2322:“可以实例化与约束'对象'的不同子类型”?
- 如何在Angular中动态加载外部脚本?
- 可观察到的。的不是一个函数