我知道这是一个非常普遍的问题,但我在Angular 2中上传文件失败了。 我试过了
1) http://valor-software.com/ng2-file-upload/
2) http://ng2-uploader.com/home
...但失败了。有人在Angular中上传过文件吗?你用了什么方法?怎么做呢?如果提供了任何示例代码或演示链接,将非常感谢。
我知道这是一个非常普遍的问题,但我在Angular 2中上传文件失败了。 我试过了
1) http://valor-software.com/ng2-file-upload/
2) http://ng2-uploader.com/home
...但失败了。有人在Angular中上传过文件吗?你用了什么方法?怎么做呢?如果提供了任何示例代码或演示链接,将非常感谢。
当前回答
根据上面的答案,我用Angular 5.x构建了这个
只需调用uploadFile(url, file).subscribe()来触发上传
import { Injectable } from '@angular/core';
import {HttpClient, HttpParams, HttpRequest, HttpEvent} from '@angular/common/http';
import {Observable} from "rxjs";
@Injectable()
export class UploadService {
constructor(private http: HttpClient) { }
// file from event.target.files[0]
uploadFile(url: string, file: File): Observable<HttpEvent<any>> {
let formData = new FormData();
formData.append('upload', file);
let params = new HttpParams();
const options = {
params: params,
reportProgress: true,
};
const req = new HttpRequest('POST', url, formData, options);
return this.http.request(req);
}
}
在组件中像这样使用它
// At the drag drop area
// (drop)="onDropFile($event)"
onDropFile(event: DragEvent) {
event.preventDefault();
this.uploadFile(event.dataTransfer.files);
}
// At the drag drop area
// (dragover)="onDragOverFile($event)"
onDragOverFile(event) {
event.stopPropagation();
event.preventDefault();
}
// At the file input element
// (change)="selectFile($event)"
selectFile(event) {
this.uploadFile(event.target.files);
}
uploadFile(files: FileList) {
if (files.length == 0) {
console.log("No file selected!");
return
}
let file: File = files[0];
this.upload.uploadFile(this.appCfg.baseUrl + "/api/flash/upload", file)
.subscribe(
event => {
if (event.type == HttpEventType.UploadProgress) {
const percentDone = Math.round(100 * event.loaded / event.total);
console.log(`File is ${percentDone}% loaded.`);
} else if (event instanceof HttpResponse) {
console.log('File is completely loaded!');
}
},
(err) => {
console.log("Upload Error:", err);
}, () => {
console.log("Upload done");
}
)
}
其他回答
这个简单的解决方案对我很有效:file-upload.component.html
<div>
<input type="file" #fileInput placeholder="Upload file..." />
<button type="button" (click)="upload()">Upload</button>
</div>
然后在组件中直接使用XMLHttpRequest进行上传。
import { Component, OnInit, ViewChild } from '@angular/core';
@Component({
selector: 'app-file-upload',
templateUrl: './file-upload.component.html',
styleUrls: ['./file-upload.component.css']
})
export class FileUploadComponent implements OnInit {
@ViewChild('fileInput') fileInput;
constructor() { }
ngOnInit() {
}
private upload() {
const fileBrowser = this.fileInput.nativeElement;
if (fileBrowser.files && fileBrowser.files[0]) {
const formData = new FormData();
formData.append('files', fileBrowser.files[0]);
const xhr = new XMLHttpRequest();
xhr.open('POST', '/api/Data/UploadFiles', true);
xhr.onload = function () {
if (this['status'] === 200) {
const responseText = this['responseText'];
const files = JSON.parse(responseText);
//todo: emit event
} else {
//todo: error handling
}
};
xhr.send(formData);
}
}
}
如果使用dotnet core,参数名必须与from字段名匹配。本例中的文件:
[HttpPost("[action]")]
public async Task<IList<FileDto>> UploadFiles(List<IFormFile> files)
{
return await _binaryService.UploadFilesAsync(files);
}
这个答案抄袭了http://blog.teamtreehouse.com/uploading-files-ajax
编辑: 上传后,您必须清除文件上传,以便用户可以选择一个新文件。与其使用XMLHttpRequest,不如使用fetch:
private addFileInput() {
const fileInputParentNative = this.fileInputParent.nativeElement;
const oldFileInput = fileInputParentNative.querySelector('input');
const newFileInput = document.createElement('input');
newFileInput.type = 'file';
newFileInput.multiple = true;
newFileInput.name = 'fileInput';
const uploadfiles = this.uploadFiles.bind(this);
newFileInput.onchange = uploadfiles;
oldFileInput.parentNode.replaceChild(newFileInput, oldFileInput);
}
private uploadFiles() {
this.onUploadStarted.emit();
const fileInputParentNative = this.fileInputParent.nativeElement;
const fileInput = fileInputParentNative.querySelector('input');
if (fileInput.files && fileInput.files.length > 0) {
const formData = new FormData();
for (let i = 0; i < fileInput.files.length; i++) {
formData.append('files', fileInput.files[i]);
}
const onUploaded = this.onUploaded;
const onError = this.onError;
const addFileInput = this.addFileInput.bind(this);
fetch('/api/Data/UploadFiles', {
credentials: 'include',
method: 'POST',
body: formData,
}).then((response: any) => {
if (response.status !== 200) {
const error = `An error occured. Status: ${response.status}`;
throw new Error(error);
}
return response.json();
}).then(files => {
onUploaded.emit(files);
addFileInput();
}).catch((error) => {
onError.emit(error);
});
}
https://github.com/yonexbat/cran/blob/master/cranangularclient/src/app/file-upload/file-upload.component.ts
尽量不要设置options参数
这个http post(美元(this。apiEndPoint), formData)
并且确保你没有在你的Http工厂中设置globalHeaders。
由于代码示例有点过时,我想我应该分享一个更近期的方法,使用Angular 4.3和新的HttpClient API @angular/common/http
export class FileUpload {
@ViewChild('selectedFile') selectedFileEl;
uploadFile() {
let params = new HttpParams();
let formData = new FormData();
formData.append('upload', this.selectedFileEl.nativeElement.files[0])
const options = {
headers: new HttpHeaders().set('Authorization', this.loopBackAuth.accessTokenId),
params: params,
reportProgress: true,
withCredentials: true,
}
this.http.post('http://localhost:3000/api/FileUploads/fileupload', formData, options)
.subscribe(
data => {
console.log("Subscribe data", data);
},
(err: HttpErrorResponse) => {
console.log(err.message, JSON.parse(err.error).error.message);
}
)
.add(() => this.uploadBtn.nativeElement.disabled = false);//teardown
}
我已经上传文件使用引用。以这种方式上传文件不需要包。
//要写入.ts文件的代码
@ViewChild("fileInput") fileInput;
addFile(): void {
let fi = this.fileInput.nativeElement;
if (fi.files && fi.files[0]) {
let fileToUpload = fi.files[0];
this.admin.addQuestionApi(fileToUpload)
.subscribe(
success => {
this.loading = false;
this.flashMessagesService.show('Uploaded successfully', {
classes: ['alert', 'alert-success'],
timeout: 1000,
});
},
error => {
this.loading = false;
if(error.statusCode==401) this.router.navigate(['']);
else
this.flashMessagesService.show(error.message, {
classes: ['alert', 'alert-danger'],
timeout: 1000,
});
});
}
}
//服务中要编写的代码。ts文件
addQuestionApi(fileToUpload: any){
var headers = this.getHeadersForMultipart();
let input = new FormData();
input.append("file", fileToUpload);
return this.http.post(this.baseUrl+'addQuestions', input, {headers:headers})
.map(response => response.json())
.catch(this.errorHandler);
}
//用HTML编写的代码
<input type="file" #fileInput>
感谢@Eswar。这段代码非常适合我。我想在解决方案中添加一些东西:
我得到错误:java.io.IOException: RESTEASY007550:无法获得多部分的边界
为了解决这个错误,你应该删除“Content-Type”“multipart/form-data”。它解决了我的问题。