英文:
Defined variable gets back to undefined inside subscribe
问题
我是初学者,所以我觉得可能做错了一些事情。
我试着编写一个CRUD,允许在创建团队时向团队添加图像。
我将文件名存储在数据库中,然后将图像上传到服务器后端。几天前,一切都正常工作,但从昨天开始,它就无法上传文件了。这是因为变量this.currentFile
在每次输入更改时都被定义,但在从API接收的数据分配给this.team
(this.team
也是未定义的,而data
是已定义的)后会重新变为未定义。
我找到有人说subscribe()
中的this
未定义,但我的已经定义好了。
我真的不知道是什么问题,我已经花了好几个小时在这上面,但我没有找到任何可以帮助的东西,所以非常感谢任何帮助!
这是team-form.component.ts
中的submit()
方法:
submit() {
this.bindToModel();
if (this.team.id == undefined) {
this.teamService.save(this.team).subscribe(
(data) => {
this.team = data;
if (this.currentFile != undefined) {
this.uploadService.upload(this.currentFile, this.team.id).subscribe({
error: err => showError(this.toasterService, err.error.message),
complete: () => {
this.currentFile = null;
}
});
}
},
error => showError(this.toasterService, error.message),
() => { this.closeModalAndMessageSuccess() }
);
} else {
this.teamService.update(this.team).subscribe({
error: err => showError(this.toasterService, err.error.message),
complete: () => this.closeModalAndMessageSuccess()
})
}
}
这是bindToModel()
方法:
bindToModel() {
this.team.contestTypes = this.selectedContestTypes;
this.selectedContestTypes = [];
this.team.label = this.teamForm.get('label').value;
if (this.currentFile != undefined) {
this.team.logoPath = this.currentFile.name;
} else {
this.team.logoPath = null;
}
}
这是当用户选择文件时触发的selectFile(event)
方法:
selectFile(event) {
let reader = new FileReader();
if (event.target.files && event.target.files.length > 0) {
this.currentFile = event.target.files[0];
}
}
这是输入字段的HTML代码:
<div class="labelAndUpload">
<label for="teamLogo"> Logo de l'équipe</label>
<input type="file"
id="teamLogo"
(change)="selectFile($event)">
</div>
编辑:
正如@aditya_adi_98建议的那样,我同时进行了上传文件和保存团队的调用。
现在我认为我在后端控制器方法的语法方面有问题,因为我得到了以下错误:
不支持内容类型'multipart/form-data;boundary=---------------------------29202803211777703984242234963'
这是我的新submit()
方法:
submit() {
this.bindToModel();
if (this.team.id == undefined) {
var stringTeam = JSON.stringify(this.team);
const frmData = new FormData();
frmData.append("team", stringTeam);
frmData.append("file", this.currentFile);
this.teamService.save(frmData).subscribe({
error: err => showError(this.toasterService, err.error.message),
complete: () => this.closeModalAndMessageSuccess()
});
} else {
this.teamService.update(this.team).subscribe({
error: err => showError(this.toasterService, err.error.message),
complete: () => this.closeModalAndMessageSuccess()
})
}
}
现在是请求部分:
public save(formData: FormData) {
return this.http.post<Team>(this.teamsUrl, formData);
}
以及后端控制器方法(Java)。目前尚未修改该方法以考虑我传递的文件,但我只是想让该方法正确接收请求。
@PostMapping(path = TEAMS_URI, consumes = "application/json", produces = "application/json")
@PreAuthorize("hasRole('ADMIN')")
public ResponseEntity<?> createTeam(@Valid @RequestParam("team") Team team, @RequestParam("file") MultipartFile file) throws URISyntaxException {
String message = bundle.getString(POST_TEAM);
log.debug(message, team);
Team teamSave = teamService.createTeam(team);
return new ResponseEntity<>(teamSave, HttpStatus.CREATED);
}
有没有了解Java的人可以帮助我?
英文:
I'm a beginner so I think I might doing something wrong.
I try to code a CRUD that allows to add an image to a team when you create one.
I store the name of the file in the database and then I upload the image on the server back-end. A few days ago, everything was working perfectly but since yesterday, it won't upload the file. This is because the variable this.currentFile
, which is defined on every change on the input, gets back to undefined after the data received from API was assigned to this.team
(which is also undefined, whereas data
is defined).
I found someone that said that this
was undefined in subscribe()
but mine is well defined.
I really don't know what's wrong, it's been hours I'm on this and I didn't find anything that could help, so any help would be greatly appreciated !
So here is the submit()
method in team-form.component.ts
submit() {
this.bindToModel();
if(this.team.id == undefined) { //this.team and this.currentFile are well defined
this.teamService.save(this.team).subscribe(
(data) => {
this.team = data; //this.team and this.currentFile get back to undefined at this point, even after data was assigned to this.team
if(this.currentFile != undefined) {
this.uploadService.upload(this.currentFile, this.team.id).subscribe({
error: err => showError(this.toasterService, err.error.message),
complete: () => {
this.currentFile = null;
}
});
}
},
error => showError(this.toasterService, error.message),
() => { this.closeModalAndMessageSuccess()}
);
}else {
this.teamService.update(this.team).subscribe({
error: err => showError(this.toasterService, err.error.message),
complete: () => this.closeModalAndMessageSuccess()
})
}
}
Here is the bindToModel()
method
bindToModel() {
this.team.contestTypes = this.selectedContestTypes;
this.selectedContestTypes = [];
this.team.label = this.teamForm.get('label').value;
if(this.currentFile != undefined) {
this.team.logoPath = this.currentFile.name;
} else {
this.team.logoPath = null;
}
}
And the selectFile(event)
method triggered when the user selects a file
selectFile(event) {
let reader = new FileReader();
if(event.target.files && event.target.files.length > 0) {
this.currentFile = event.target.files[0];
}
}
And the html of the input :
<div class="labelAndUpload">
<label for="teamLogo"> Logo de l'équipe</label>
<input type="file"
id="teamLogo"
(change)="selectFile($event)">
</div>
EDIT :
So as @aditya_adi_98 suggested, I made a call to upload the file and save the team at the same time.
Now I think I have an issue with my back-end controller method syntax because I've got the following error :
Content type 'multipart/form-data;boundary=---------------------------29202803211777703984242234963' not supported
Here is my new submit()
method
submit() {
this.bindToModel();
if(this.team.id == undefined) {
var stringTeam = JSON.stringify(this.team);
const frmData = new FormData();
frmData.append("team", stringTeam);
frmData.append("file", this.currentFile);
this.teamService.save(frmData).subscribe({
error: err => showError(this.toasterService, err.error.message),
complete: () => this.closeModalAndMessageSuccess()
});
} else {
this.teamService.update(this.team).subscribe({
error: err => showError(this.toasterService, err.error.message),
complete: () => this.closeModalAndMessageSuccess()
})
}
}
Now the request
public save(formData: FormData) {
return this.http.post<Team>(this.teamsUrl, formData);
}
And the back-end controller method (java). It's not modified yet to take in account the file I'm passing, but I just want the method to receive the request properly at the moment.
@PostMapping(path = TEAMS_URI, consumes = "application/json", produces = "application/json")
@PreAuthorize("hasRole('ADMIN')")
public ResponseEntity<?> createTeam(@Valid @RequestParam("team") Team team, @RequestParam("file") MultipartFile file) throws URISyntaxException {
String message = bundle.getString(POST_TEAM);
log.debug(message, team);
Team teamSave = teamService.createTeam(team);
return new ResponseEntity<>(teamSave, HttpStatus.CREATED);
}
Anyone who knows java here can help me?
答案1
得分: 1
以下是翻译好的内容:
为什么要进行两次 HTTP 调用,而你可以在一次调用中完成,就像这样使用 this.teamService.save(this.team)
:
const frmData = new FormData();
frmData.append("Upload", this.currentFile);
frmData.append("team", this.team);
编辑:
你还可以这样做来观察文件上传的过程,最好是发送一个完整的请求,然后等待响应:
this.http.post(BACKEND_URL+'/testfileupload', frmData, { responseType: 'text', reportProgress: true, observe: 'events' })
.subscribe(
(event: HttpEvent<any>) => {
switch (event.type) {
case HttpEventType.Sent:
break;
case HttpEventType.ResponseHeader:
break;
case HttpEventType.UploadProgress:
this.progress = Math.round(event.loaded / event.total * 100);
this.showupload = true;
this.changedetector.detectChanges();
console.log(`已上传 ${this.progress}%`);
break;
case HttpEventType.Response:
this.showupload = false;
this.doneupload = true;
this.progress = 0;
this.currentFile = '';
this.changedetector.detectChanges();
console.log("上传成功");
this.teamaddedsuccessful();
setTimeout(() => {
this.doneupload = false;
this.changedetector.detectChanges();
this.modalService.dismissAll();
this.toastr.success("文件上传成功", "成功");
this.filetitle = '';
}, 3000);
}
},
res => {
if (res.status == 404) {
this.showupload = false;
this.progress = 0;
this.changedetector.detectChanges();
this.toastr.error("文件上传出错", "错误");
}
}
);
英文:
Why are you doing two http calls where you can do this in one call..like send the file/image with this.teamService.save(this.team)
const frmData = new FormData();
frmData.append("Upload", this.currentFile);
frmData.append("team",this.team)
An Edit
you can also do this to watch your files getting uploaded, it is better to send a complete request and then wait for a response
this.http.post(BACKEND_URL+'/testfileupload', frmData,{responseType : 'text',reportProgress:true,observe :'events'})
.subscribe(
(event: HttpEvent<any>)=>{
switch(event.type){
case HttpEventType.Sent:
break;
case HttpEventType.ResponseHeader:
break;
case HttpEventType.UploadProgress:
this.progress = Math.round(event.loaded / event.total * 100);
this.showupload=true;
this.changedetector.detectChanges()
console.log(`uploaded ${this.progress}`);
break;
case HttpEventType.Response:
this.showupload=false;
this.doneupload=true;
this.progress=0;
this.currentFile=''
this.changedetector.detectChanges();
console.log("uploaded successfully")
this.teamaddedsuccessful()
setTimeout(()=>{
this.doneupload=false;
this.changedetector.detectChanges();
this.modalService.dismissAll();
this.toastr.success("File Uploaded Successful","Success")
this.filetitle='';},3000)
}
},res=>{
if(res.status == 404)
{
this.showupload=false;
this.progress=0;
this.changedetector.detectChanges();
this.toastr.error("Error in File Upload","Error")
}
})
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论