英文:
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'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
<!-- [...] -->
<!-----------------------------------------
img profile
-------------------------------------------->
<div
class="profileImg"
[ngStyle]="{ 'background-image': 'url(' + photoUrl + ')' }"
*ngIf="this.userInfos"
>
<!-- upload or change profile photo -->
<input
type="file"
accept="image/*"
style="display: none;"
#file
(change)="changeProfilePhoto($event.target.files)"
/>
<mat-icon
class="editIcon"
*ngIf="ownProfile"
(click)="file.click()"
matTooltip="Only .png or .jpg/.jpeg img with min-size: Ko and max-size: Ko"
>
edit
</mat-icon>
</div>
<!-- [...] -->
expert-profile.component.ts
// imports...
@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('---------------------REQUEST------------------------------');
this.fileService
.uploadProfilePhoto(file[0], this.profileId)
.subscribe((res) => {
console.log('changeProfilePhoto (res)', res); // test res= null
if (res == null) {
this.snackbar.open('Error (to handle) : File already uploaded', '', {
duration: 2500,
});
} else {
console.log('loading ok');
location.reload();
}
});
console.log('------------------------ END ---------------------------');
}
}
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("/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("............................ TRY ......................................");
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("....................................... CATCH: (e below) .....................................");
System.out.println(e);
System.out.println("............................................................................");
return ResponseEntity.ok().body(null);
}
}
addUserAvatar() in FileStorageService.java
/* #uploadprofilephoto #2*/
public UserInfo addUserAvatar(UUID userId, String filename, InputStream fileContent) {
System.out.println("---------------------------------------------------- ");
System.out.println(" #2 - change my profile img by "+filename);
System.out.println("---------------------------------------------------- ");
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, "avatar");
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 , "avatar");
//update the imageId in user db with the new one
//#6
user.setImage(fileEntity.getId());
System.out.println("---------------------------------------------------- ");
System.out.println(" #6 - CrudRepository save in user the new imageId: "+user.getImage());
System.out.println("---------------------------------------------------- ");
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("---------------------------------------------------- ");
System.out.println(" #3 - delete "+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 ---------------------------------------------------- ");
}
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("----------------------------------------------------");
System.out.println(" #4 add this new file in file db ");
System.out.println(fileEntity);
System.out.println("----------------------------------------------------");
return save(fileEntity).orElseThrow();
}
[...]
/**
* #uploadprofilephoto #5
* If any error happens, Optional.empty() is returned.
*/
private Optional<FileEntity> save(FileEntity file) {
System.out.println("---------------------------------------------------- ");
System.out.println(" #5 - Save ");
System.out.println("---------------------------------------------------- ");
FileEntity savedUser = fileRepository.save(file);
System.out.println("---->#5 : savedUser: "+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<T, ID> extends Repository<T, ID> {
/**
* 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}.
*/
<S extends T> S save(S entity);
[...]
}
Terminal when it fails:
(look the 2)
screenshot_1/2
screenshot_1/2
Terminal when it works:
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').
通过集体智慧和协作来改善编程学习和解决问题的方式。致力于成为全球开发者共同参与的知识库,让每个人都能够通过互相帮助和分享经验来进步。
评论