照片因数据库中尚存在而无法上传,如何覆盖?

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

Photo doesn't upload because yet in db, how to overwrite?

问题

以下是您提供的代码翻译部分:

我是Java的新手,但我正在编写的Web应用的后端是用Java编写的,我的团队中没有人可以帮助我。

我的问题:在用户个人资料组件中,我有一个输入来编辑照片,但每次都返回错误消息。

似乎是因为文件已经存在于数据库中,所以照片从未更新。

我认为在后端可能有一些问题或缺失。

前端(angular)
-------------

**expert-profile.component.html**

```lang-js
<!-- [...] -->
<!-----------------------------------------
    图片配置文件
  -------------------------------------------->
  <div
    class="profileImg"
    [ngStyle]="{ 'background-image': 'url(' + photoUrl + ')' }"
    *ngIf="this.userInfos"
  >
   <!-- 上传或更改个人资料照片 -->
    <input
      type="file"
      accept="image/*"
      style="display: none;"
      #file
      (change)="changeProfilePhoto($event.target.files)"
    />
    <mat-icon
      class="editIcon"
      *ngIf="ownProfile"
      (click)="file.click()"
      matTooltip="仅支持.png或.jpg/.jpeg格式的图片,最小大小:KB,最大大小:KB"
    >
      编辑
    </mat-icon>
  </div>
<!-- [...] -->

expert-profile.component.ts


// 导入...

@Component({
  selector: 'app-expert-profile',
  templateUrl: './expert-profile.component.html',
  styleUrls: ['./expert-profile.component.less'],
})

export class ExpertProfileComponent implements OnInit {

//[...]

async changeProfilePhoto(file: FileList) {
    console.log(' async changeProfilePhoto....', file);
    console.log('---------------------请求------------------------------');
    this.fileService
      .uploadProfilePhoto(file[0], this.profileId)
      .subscribe((res) => {
        console.log('changeProfilePhoto (res)', res); // 测试 res= null
        if (res == null) {
          this.snackbar.open('错误(待处理):文件已上传', '', {
            duration: 2500,
          });
        } else {
          console.log('加载成功');
          location.reload();
        }
      });
    console.log('------------------------ 结束 ---------------------------');
  }
}

console.log 返回--- >

[...]
------------------------ 结束 ---------------------------
changeProfilePhoto (res) null

浏览器返回 --- >
一个带有消息的 snackbar:

错误(待处理):文件已上传

照片已上传但未使用。

后端

FileUploadController.java

/* uploadprofilephoto #1 */
    @PostMapping("/user/{userId}/avatar")
    public ResponseEntity<UserInfo> uploadProfilePhoto(@PathVariable UUID userId, @RequestParam MultipartFile avatar,
                                                  HttpServletRequest request) throws IOException {
        System.out.println("............................................................................");
        System.out.println("                       uploadprofilephoto #1    ");
        System.out.println("............................................................................");                                          
        try {
            System.out.println("............................     尝试     ......................................");
           
            UserInfo u = storageService.addUserAvatar(userId, avatar.getOriginalFilename(), avatar.getInputStream());
            URI location = ServletUriComponentsBuilder.fromCurrentRequest().path("/{userId}").buildAndExpand("").toUri();
            return ResponseEntity.created(location).body(u);
        } catch(Exception e) {
            System.out.println(".......................................   捕获:(以下为 e)   .....................................");
            System.out.println(e);
            System.out.println("............................................................................");
            return ResponseEntity.ok().body(null);
        }
        
    }

FileStorageService.java 中的 addUserAvatar()

  /* #uploadprofilephoto #2*/
    public UserInfo addUserAvatar(UUID userId, String filename, InputStream fileContent) {
        System.out.println("---------------------------------------------------- ");
        System.out.println("                        #2 - 更改我的个人资料图片:  "+filename);
        System.out.println("---------------------------------------------------- ");
        UserEntity user = userServiceActions.findById(userId);

        //如果userProfile中的fileId已经存在于filedatabase中,则在filedatabase + 目录中将其删除
        //#3
        try {
            this.delete(user.getImage());
        } catch(Exception e) {}

        //为新头像创建路径+目录以存储它
        Path directory = router.getOrCreatePathFromFilename(userId, filename, "avatar");
        Path location = fileSaver.store(filename, fileContent, directory);

        //为新文件请求
        var f = new FileRequest();
        f.filename = filename;
        f.projectId = Optional.of(userId);
        MediaType mediaType = MediaType.parseMediaType(getContentType(location));
       
        //使用唯一Id为此文件创建实体,并将其添加到文件数据库中
        //#4 + #5
        FileEntity fileEntity = fileServiceActions.add(UUID.randomUUID(), mediaType.getType(), mediaType.getSubtype(), f , "avatar");
        
        //使用新的Id更新user数据库中的imageId
        //#6
        user.setImage(fileEntity.getId());
        System.out.println("---------------------------------------------------- ");
        System.out.println("                        #6 - 在用户数据库中保存新的imageId:  "+user.getImage());
        System.out.println("---------------------------------------------------- ");
        userRepository.save(user);//如果以前已经上传过带有相同文件名的照片,似乎会阻塞
       
        //返回新数据并更新个人资料
        UserInfo userInfo = mapper.map(user, UserInfo.class);
        return userInfo;
    }

FileStorageService.java 中的 delete()(一切似乎都正常)

 /* #uploadprofilephoto #3*/
    public void delete(UUID id) throws ResourceNotFoundException {
        System.out.println("---------------------------------------------------- ");
        System.out.println("                        #3 - 删除:  "+id);
        System.out.println("---------------------------------------------------- ");
    	FileEntity file = fileServiceActions.findById(id);
    	 Path directory = router.getOrCreatePathFromFilename(file.getProjectId(), file.getFilename(), file.getCategory());
    	
    	fileSaver.deleteFromDisk(directory, file.getFilename());
    	
        fileServiceActions.delete(id);
        System.out.println("end delete ---------------------------------------------------- ");
    }

FileServiceActions.java 中的 add() 和 save()(问题可能出在 save)

  /**
     * #uploadprofilephoto #4
     * 允许为文件提供预生成的UUID。当我们想在将记录添加到数据库之前获得UUID时很有用。
     */
    public FileEntity add(UUID fileId, String type, String subtype, FileRequest req , String category) {
        FileEntity fileEntity;
        
        try {
            ProjectEntity proj = null;
            proj = projectServiceActions.findById(req.projectId.orElseThrow());
            fileEntity = toEntity(proj.getId(), req, type, subtype,

<details>
<summary>英文:</summary>

I am new to Java, but the back of the web app I am coding is in Java and no one in my team can help me. 

My problem: In the user profile component, I have an input to edit the photo but every time it returns an error message.

It seems it&#39;s because file already exists in the database, so the photo is never updated.

I think there is something wrong or missing **in the back side** .

FRONT (angular)
-------------

**expert-profile.component.html**

```lang-js
&lt;!-- [...] --&gt;
&lt;!-----------------------------------------
    img profile
  --------------------------------------------&gt;
  &lt;div
    class=&quot;profileImg&quot;
    [ngStyle]=&quot;{ &#39;background-image&#39;: &#39;url(&#39; + photoUrl + &#39;)&#39; }&quot;
    *ngIf=&quot;this.userInfos&quot;
  &gt;
   &lt;!-- upload or change profile photo --&gt;
    &lt;input
      type=&quot;file&quot;
      accept=&quot;image/*&quot;
      style=&quot;display: none;&quot;
      #file
      (change)=&quot;changeProfilePhoto($event.target.files)&quot;
    /&gt;

    &lt;mat-icon
      class=&quot;editIcon&quot;
      *ngIf=&quot;ownProfile&quot;
      (click)=&quot;file.click()&quot;
      matTooltip=&quot;Only .png or .jpg/.jpeg img with min-size: Ko and max-size: Ko&quot;
    &gt;
      edit
    &lt;/mat-icon&gt;
  &lt;/div&gt;
&lt;!-- [...] --&gt;

expert-profile.component.ts


// imports...

@Component({
  selector: &#39;app-expert-profile&#39;,
  templateUrl: &#39;./expert-profile.component.html&#39;,
  styleUrls: [&#39;./expert-profile.component.less&#39;],
})

export class ExpertProfileComponent implements OnInit {

//[...]

async changeProfilePhoto(file: FileList) {
    console.log(&#39; async changeProfilePhoto....&#39;, file);
    console.log(&#39;---------------------REQUEST------------------------------&#39;);
    this.fileService
      .uploadProfilePhoto(file[0], this.profileId)
      .subscribe((res) =&gt; {
        console.log(&#39;changeProfilePhoto (res)&#39;, res); // test res= null
        if (res == null) {
          this.snackbar.open(&#39;Error (to handle) : File already uploaded&#39;, &#39;&#39;, {
            duration: 2500,
          });
        } else {
          console.log(&#39;loading ok&#39;);
          location.reload();
        }
      });
    console.log(&#39;------------------------ END ---------------------------&#39;);
  }
}

console.log return--->

[...]
------------------------ END ---------------------------
changeProfilePhoto (res) null

browser return --->
a snackbar with message:
>Error (to handle) : File already uploaded

Photo is uploaded but not used.

Back End

FileUploadController.java

/* uploadprofilephoto #1 */
    @PostMapping(&quot;/user/{userId}/avatar&quot;)
    public ResponseEntity&lt;UserInfo&gt; uploadProfilePhoto(@PathVariable UUID userId, @RequestParam MultipartFile avatar,
                                                  HttpServletRequest request) throws IOException {
        System.out.println(&quot;............................................................................&quot;);
        System.out.println(&quot;                       uploadprofilephoto #1    &quot;);
            System.out.println(&quot;............................................................................&quot;);                                          
        try {
            System.out.println(&quot;............................     TRY     ......................................&quot;);
           
            UserInfo u = storageService.addUserAvatar(userId, avatar.getOriginalFilename(), avatar.getInputStream());
            URI location = ServletUriComponentsBuilder.fromCurrentRequest().path(&quot;/{userId}&quot;).buildAndExpand(&quot;&quot;).toUri();
            return ResponseEntity.created(location).body(u);
        } catch(Exception e) {
            System.out.println(&quot;.......................................   CATCH: (e below)   .....................................&quot;);
            System.out.println(e);
            System.out.println(&quot;............................................................................&quot;);
            return ResponseEntity.ok().body(null);
        }
        
    }

addUserAvatar() in FileStorageService.java

  /* #uploadprofilephoto #2*/
    public UserInfo addUserAvatar(UUID userId, String filename, InputStream fileContent) {
        System.out.println(&quot;---------------------------------------------------- &quot;);
        System.out.println(&quot;                        #2 - change my profile img by    &quot;+filename);
        System.out.println(&quot;---------------------------------------------------- &quot;);
        UserEntity user = userServiceActions.findById(userId);

        //If fileId in userProfile is already present in filedatabase , it delete it in filedatabase + directory
        //#3
        try {
            this.delete(user.getImage());
        } catch(Exception e) {}

        //create path for a new avatar + directory to store it
        Path directory = router.getOrCreatePathFromFilename(userId, filename, &quot;avatar&quot;);
        Path location = fileSaver.store(filename, fileContent, directory);

        //request for a new file
        var f = new FileRequest();
        f.filename = filename;
        f.projectId = Optional.of(userId);
        MediaType mediaType = MediaType.parseMediaType(getContentType(location));
       
        //Create an entity for this file with a uniq Id, and add it in file db
        //#4 + #5
        FileEntity fileEntity = fileServiceActions.add(UUID.randomUUID(), mediaType.getType(), mediaType.getSubtype(), f , &quot;avatar&quot;);
        
        //update the imageId in user db with the new one
        //#6
        user.setImage(fileEntity.getId());
        System.out.println(&quot;---------------------------------------------------- &quot;);
        System.out.println(&quot;                        #6 - CrudRepository save in user the new imageId:   &quot;+user.getImage());
        System.out.println(&quot;---------------------------------------------------- &quot;);
        userRepository.save(user);//seems to block if a photo was allready uploaded by past with the same filename
       
        //return the new data and update profile
        UserInfo userInfo = mapper.map(user, UserInfo.class);
        return userInfo;
    }

(see return of console print below)

delete() in FileStorageService.java (everything seems ok)

 /* #uploadprofilephoto #3*/
    public void delete(UUID id) throws ResourceNotFoundException {
        System.out.println(&quot;---------------------------------------------------- &quot;);
        System.out.println(&quot;                        #3 - delete    &quot;+id);
        System.out.println(&quot;---------------------------------------------------- &quot;);
    	FileEntity file = fileServiceActions.findById(id);
    	 Path directory = router.getOrCreatePathFromFilename(file.getProjectId(), file.getFilename(), file.getCategory());
    	
    	fileSaver.deleteFromDisk(directory, file.getFilename());
    	
        fileServiceActions.delete(id);
        System.out.println(&quot;end delete ---------------------------------------------------- &quot;);
    }

add() & save() in FileServiceActions.java (Pb comes from the save according to me )

  /**
     * #uploadprofilephoto #4
     * Allows to give a pre-generated UUID to the file. Useful when we want to have the
     * UUID before adding a record to the database.
     */
    public FileEntity add(UUID fileId, String type, String subtype, FileRequest req , String category) {
        FileEntity fileEntity;
        
        try {
            ProjectEntity proj = null;
            proj = projectServiceActions.findById(req.projectId.orElseThrow());
            fileEntity = toEntity(proj.getId(), req, type, subtype, category);
        } catch(Exception e) {
            UserEntity user = null;
            user = userServiceActions.findById(req.projectId.orElseThrow());
            fileEntity = toEntity(user.getId(), req, type, subtype, category);
        }
        fileEntity.setId(fileId);
        System.out.println(&quot;----------------------------------------------------&quot;);
        System.out.println(&quot;                        #4 add this new file in file db    &quot;);
        System.out.println(fileEntity);
        System.out.println(&quot;----------------------------------------------------&quot;);
        return save(fileEntity).orElseThrow();
    }

[...]

/**
     * #uploadprofilephoto #5
     * If any error happens, Optional.empty() is returned.
     */
    private Optional&lt;FileEntity&gt; save(FileEntity file) {
        System.out.println(&quot;---------------------------------------------------- &quot;);
        System.out.println(&quot;                        #5 - Save   &quot;);
        System.out.println(&quot;---------------------------------------------------- &quot;);
        FileEntity savedUser = fileRepository.save(file);
        System.out.println(&quot;----&gt;#5 : savedUser: &quot;+savedUser);//pb is during the save, this consolePrint never be return when img allready exist in db
        return Optional.ofNullable(savedUser);
    }

save() in CrudRepository.class ('Pb' comes from this save according to me )


@NoRepositoryBean
public interface CrudRepository&lt;T, ID&gt; extends Repository&lt;T, ID&gt; {

	/**
	 * Saves a given entity. Use the returned instance for further operations as the save operation might have changed the
	 * entity instance completely.
	 *
	 * @param entity must not be {@literal null}.
	 * @return the saved entity will never be {@literal null}.
	 */
	&lt;S extends T&gt; S save(S entity);

[...]
}

Terminal when it fails:

(look the 2)
screenshot_1/2
screenshot_1/2

Terminal when it works:

screenshot

Somebody have an idea How to resolve my problem?

I think the solution is
either:

  • if fileName allready exist , just change the id by the newOne (or catch its id and use it for the imageId in user db)
    or:
    -if fileName allready exist , delete it and save the newOne

What do you think about this solution?
How to code it in Java?

答案1

得分: 0

我修复了我的问题。
根据规格的更新,我只在数据库和目录中为每个用户保留一张图片/头像。

因此,我已将删除操作(delete(user.imageId))更改为删除所有与用户ID和类别('avatar')匹配的项。

英文:

I fixed my pb.
According to the update of the specifications, I keep in db and directory only one img/avatar for each user.

So I have changed the delete(user.imageId) by deleteAllByUserIdAndCategory(user.id, 'avatar').

huangapple
  • 本文由 发表于 2020年8月27日 23:16:45
  • 转载请务必保留本文链接:https://go.coder-hub.com/63619117.html
匿名

发表评论

匿名网友

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

确定