已定义的变量在订阅内部变为未定义状态。

huangapple go评论108阅读模式
英文:

Defined variable gets back to undefined inside subscribe

问题

我是初学者,所以我觉得可能做错了一些事情。
我试着编写一个CRUD,允许在创建团队时向团队添加图像。
我将文件名存储在数据库中,然后将图像上传到服务器后端。几天前,一切都正常工作,但从昨天开始,它就无法上传文件了。这是因为变量this.currentFile在每次输入更改时都被定义,但在从API接收的数据分配给this.teamthis.team也是未定义的,而data是已定义的)后会重新变为未定义。

我找到有人说subscribe()中的this未定义,但我的已经定义好了。
我真的不知道是什么问题,我已经花了好几个小时在这上面,但我没有找到任何可以帮助的东西,所以非常感谢任何帮助!

这是team-form.component.ts中的submit()方法:

  1. submit() {
  2. this.bindToModel();
  3. if (this.team.id == undefined) {
  4. this.teamService.save(this.team).subscribe(
  5. (data) => {
  6. this.team = data;
  7. if (this.currentFile != undefined) {
  8. this.uploadService.upload(this.currentFile, this.team.id).subscribe({
  9. error: err => showError(this.toasterService, err.error.message),
  10. complete: () => {
  11. this.currentFile = null;
  12. }
  13. });
  14. }
  15. },
  16. error => showError(this.toasterService, error.message),
  17. () => { this.closeModalAndMessageSuccess() }
  18. );
  19. } else {
  20. this.teamService.update(this.team).subscribe({
  21. error: err => showError(this.toasterService, err.error.message),
  22. complete: () => this.closeModalAndMessageSuccess()
  23. })
  24. }
  25. }

这是bindToModel()方法:

  1. bindToModel() {
  2. this.team.contestTypes = this.selectedContestTypes;
  3. this.selectedContestTypes = [];
  4. this.team.label = this.teamForm.get('label').value;
  5. if (this.currentFile != undefined) {
  6. this.team.logoPath = this.currentFile.name;
  7. } else {
  8. this.team.logoPath = null;
  9. }
  10. }

这是当用户选择文件时触发的selectFile(event)方法:

  1. selectFile(event) {
  2. let reader = new FileReader();
  3. if (event.target.files && event.target.files.length > 0) {
  4. this.currentFile = event.target.files[0];
  5. }
  6. }

这是输入字段的HTML代码:

  1. <div class="labelAndUpload">
  2. <label for="teamLogo"> Logo de l'équipe</label>
  3. <input type="file"
  4. id="teamLogo"
  5. (change)="selectFile($event)">
  6. </div>

编辑:

正如@aditya_adi_98建议的那样,我同时进行了上传文件和保存团队的调用。
现在我认为我在后端控制器方法的语法方面有问题,因为我得到了以下错误:

  1. 不支持内容类型'multipart/form-data;boundary=---------------------------29202803211777703984242234963'

这是我的新submit()方法:

  1. submit() {
  2. this.bindToModel();
  3. if (this.team.id == undefined) {
  4. var stringTeam = JSON.stringify(this.team);
  5. const frmData = new FormData();
  6. frmData.append("team", stringTeam);
  7. frmData.append("file", this.currentFile);
  8. this.teamService.save(frmData).subscribe({
  9. error: err => showError(this.toasterService, err.error.message),
  10. complete: () => this.closeModalAndMessageSuccess()
  11. });
  12. } else {
  13. this.teamService.update(this.team).subscribe({
  14. error: err => showError(this.toasterService, err.error.message),
  15. complete: () => this.closeModalAndMessageSuccess()
  16. })
  17. }
  18. }

现在是请求部分:

  1. public save(formData: FormData) {
  2. return this.http.post<Team>(this.teamsUrl, formData);
  3. }

以及后端控制器方法(Java)。目前尚未修改该方法以考虑我传递的文件,但我只是想让该方法正确接收请求。

  1. @PostMapping(path = TEAMS_URI, consumes = "application/json", produces = "application/json")
  2. @PreAuthorize("hasRole('ADMIN')")
  3. public ResponseEntity<?> createTeam(@Valid @RequestParam("team") Team team, @RequestParam("file") MultipartFile file) throws URISyntaxException {
  4. String message = bundle.getString(POST_TEAM);
  5. log.debug(message, team);
  6. Team teamSave = teamService.createTeam(team);
  7. return new ResponseEntity<>(teamSave, HttpStatus.CREATED);
  8. }

有没有了解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

  1. submit() {
  2. this.bindToModel();
  3. if(this.team.id == undefined) { //this.team and this.currentFile are well defined
  4. this.teamService.save(this.team).subscribe(
  5. (data) =&gt; {
  6. this.team = data; //this.team and this.currentFile get back to undefined at this point, even after data was assigned to this.team
  7. if(this.currentFile != undefined) {
  8. this.uploadService.upload(this.currentFile, this.team.id).subscribe({
  9. error: err =&gt; showError(this.toasterService, err.error.message),
  10. complete: () =&gt; {
  11. this.currentFile = null;
  12. }
  13. });
  14. }
  15. },
  16. error =&gt; showError(this.toasterService, error.message),
  17. () =&gt; { this.closeModalAndMessageSuccess()}
  18. );
  19. }else {
  20. this.teamService.update(this.team).subscribe({
  21. error: err =&gt; showError(this.toasterService, err.error.message),
  22. complete: () =&gt; this.closeModalAndMessageSuccess()
  23. })
  24. }
  25. }

Here is the bindToModel() method

  1. bindToModel() {
  2. this.team.contestTypes = this.selectedContestTypes;
  3. this.selectedContestTypes = [];
  4. this.team.label = this.teamForm.get(&#39;label&#39;).value;
  5. if(this.currentFile != undefined) {
  6. this.team.logoPath = this.currentFile.name;
  7. } else {
  8. this.team.logoPath = null;
  9. }
  10. }

And the selectFile(event) method triggered when the user selects a file

  1. selectFile(event) {
  2. let reader = new FileReader();
  3. if(event.target.files &amp;&amp; event.target.files.length &gt; 0) {
  4. this.currentFile = event.target.files[0];
  5. }
  6. }

And the html of the input :

  1. &lt;div class=&quot;labelAndUpload&quot;&gt;
  2. &lt;label for=&quot;teamLogo&quot;&gt; Logo de l&#39;&#233;quipe&lt;/label&gt;
  3. &lt;input type=&quot;file&quot;
  4. id=&quot;teamLogo&quot;
  5. (change)=&quot;selectFile($event)&quot;&gt;
  6. &lt;/div&gt;

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 :

  1. Content type &#39;multipart/form-data;boundary=---------------------------29202803211777703984242234963&#39; not supported

Here is my new submit() method

  1. submit() {
  2. this.bindToModel();
  3. if(this.team.id == undefined) {
  4. var stringTeam = JSON.stringify(this.team);
  5. const frmData = new FormData();
  6. frmData.append(&quot;team&quot;, stringTeam);
  7. frmData.append(&quot;file&quot;, this.currentFile);
  8. this.teamService.save(frmData).subscribe({
  9. error: err =&gt; showError(this.toasterService, err.error.message),
  10. complete: () =&gt; this.closeModalAndMessageSuccess()
  11. });
  12. } else {
  13. this.teamService.update(this.team).subscribe({
  14. error: err =&gt; showError(this.toasterService, err.error.message),
  15. complete: () =&gt; this.closeModalAndMessageSuccess()
  16. })
  17. }
  18. }

Now the request

  1. public save(formData: FormData) {
  2. return this.http.post&lt;Team&gt;(this.teamsUrl, formData);
  3. }

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.

  1. @PostMapping(path = TEAMS_URI, consumes = &quot;application/json&quot;, produces = &quot;application/json&quot;)
  2. @PreAuthorize(&quot;hasRole(&#39;ADMIN&#39;)&quot;)
  3. public ResponseEntity&lt;?&gt; createTeam(@Valid @RequestParam(&quot;team&quot;) Team team, @RequestParam(&quot;file&quot;) MultipartFile file) throws URISyntaxException {
  4. String message = bundle.getString(POST_TEAM);
  5. log.debug(message, team);
  6. Team teamSave = teamService.createTeam(team);
  7. return new ResponseEntity&lt;&gt;(teamSave, HttpStatus.CREATED);
  8. }

Anyone who knows java here can help me?

答案1

得分: 1

以下是翻译好的内容:

为什么要进行两次 HTTP 调用,而你可以在一次调用中完成,就像这样使用 this.teamService.save(this.team)

  1. const frmData = new FormData();
  2. frmData.append("Upload", this.currentFile);
  3. frmData.append("team", this.team);

编辑:

你还可以这样做来观察文件上传的过程,最好是发送一个完整的请求,然后等待响应:

  1. this.http.post(BACKEND_URL+'/testfileupload', frmData, { responseType: 'text', reportProgress: true, observe: 'events' })
  2. .subscribe(
  3. (event: HttpEvent<any>) => {
  4. switch (event.type) {
  5. case HttpEventType.Sent:
  6. break;
  7. case HttpEventType.ResponseHeader:
  8. break;
  9. case HttpEventType.UploadProgress:
  10. this.progress = Math.round(event.loaded / event.total * 100);
  11. this.showupload = true;
  12. this.changedetector.detectChanges();
  13. console.log(`已上传 ${this.progress}%`);
  14. break;
  15. case HttpEventType.Response:
  16. this.showupload = false;
  17. this.doneupload = true;
  18. this.progress = 0;
  19. this.currentFile = '';
  20. this.changedetector.detectChanges();
  21. console.log("上传成功");
  22. this.teamaddedsuccessful();
  23. setTimeout(() => {
  24. this.doneupload = false;
  25. this.changedetector.detectChanges();
  26. this.modalService.dismissAll();
  27. this.toastr.success("文件上传成功", "成功");
  28. this.filetitle = '';
  29. }, 3000);
  30. }
  31. },
  32. res => {
  33. if (res.status == 404) {
  34. this.showupload = false;
  35. this.progress = 0;
  36. this.changedetector.detectChanges();
  37. this.toastr.error("文件上传出错", "错误");
  38. }
  39. }
  40. );
英文:

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)

  1. const frmData = new FormData();
  2. frmData.append(&quot;Upload&quot;, this.currentFile);
  3. frmData.append(&quot;team&quot;,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

  1. this.http.post(BACKEND_URL+&#39;/testfileupload&#39;, frmData,{responseType : &#39;text&#39;,reportProgress:true,observe :&#39;events&#39;})
  2. .subscribe(
  3. (event: HttpEvent&lt;any&gt;)=&gt;{
  4. switch(event.type){
  5. case HttpEventType.Sent:
  6. break;
  7. case HttpEventType.ResponseHeader:
  8. break;
  9. case HttpEventType.UploadProgress:
  10. this.progress = Math.round(event.loaded / event.total * 100);
  11. this.showupload=true;
  12. this.changedetector.detectChanges()
  13. console.log(`uploaded ${this.progress}`);
  14. break;
  15. case HttpEventType.Response:
  16. this.showupload=false;
  17. this.doneupload=true;
  18. this.progress=0;
  19. this.currentFile=&#39;&#39;
  20. this.changedetector.detectChanges();
  21. console.log(&quot;uploaded successfully&quot;)
  22. this.teamaddedsuccessful()
  23. setTimeout(()=&gt;{
  24. this.doneupload=false;
  25. this.changedetector.detectChanges();
  26. this.modalService.dismissAll();
  27. this.toastr.success(&quot;File Uploaded Successful&quot;,&quot;Success&quot;)
  28. this.filetitle=&#39;&#39;;},3000)
  29. }
  30. },res=&gt;{
  31. if(res.status == 404)
  32. {
  33. this.showupload=false;
  34. this.progress=0;
  35. this.changedetector.detectChanges();
  36. this.toastr.error(&quot;Error in File Upload&quot;,&quot;Error&quot;)
  37. }
  38. })

huangapple
  • 本文由 发表于 2020年9月10日 16:04:46
  • 转载请务必保留本文链接:https://go.coder-hub.com/63825376.html
匿名

发表评论

匿名网友

:?: :razz: :sad: :evil: :!: :smile: :oops: :grin: :eek: :shock: :???: :cool: :lol: :mad: :twisted: :roll: :wink: :idea: :arrow: :neutral: :cry: :mrgreen:

确定