java - 发布 POST 请求时,Angular 中的文件上传会出错
问题描述
我有一个这样的 HTML 表单,可以将文件从前端上传到后端并执行一些操作:
<button mat-raised-button color="primary" type="button" style='margin-right:20px' (click)="selectFile()">Select File To Upload</button>
<input #fileUploadInput type="file" id="fileUpload" hidden name="avatar" (change)="fileChangeEvent($event)">
<button mat-raised-button color="primary" type="button" style='margin-right:20px' enctype="multipart/form-data" (click)="uploadFile()">Submit</button>
<br><br>
<a class="generate-full-width" style="color: darkred;" *ngIf="fileName"><strong>{{fileName}}</strong></a>
component.ts 是:
export class uploadFileDialog {
constructor(
public dialogRef: MatDialogRef<AddProductDialog>,
private uploadService: UploadService,
private builder: FormBuilder, public dialog: MatDialog,
@Inject(MAT_DIALOG_DATA) public data) {
}
@ViewChild('fileUploadInput', {static: false})
fileUploadVariable: ElementRef;
fileName;
currentFile: File;
filesToUpload = [];
resetFile(){
this.fileUploadVariable.nativeElement.value = "";
}
selectFile(){
this.resetFile();
let el: HTMLElement = this.fileUploadVariable.nativeElement as HTMLElement;
el.click();
}
fileChangeEvent(fileInput: any) {
let file = fileInput.target.files[0]
console.log(file)
//console.log(file.data.toString());
this.filesToUpload = [];
this.filesToUpload.push(file);
this.fileName = file['name'];
}
uploadFile(){
this.currentFile = this.fileName;
console.log(this.currentFile);
this.uploadService.uploadFile(this.currentFile)
.subscribe((data) => {
console.log(data)
},
error => {
console.log(error)
});
}
}
Service.ts 是:
uploadFile(file: File): Observable<any> {
let headers = new HttpHeaders({
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
//'Access-Control-Allow-Headers': 'X-Requested-With, content-type, Authorization'
'Access-Control-Allow-Headers': 'Content-Type,Accept,X-Access-Token,X-Key,Authorization,X-Requested-With,Origin,Access-Control-Allow-Origin,Access-Control-Allow-Credentials,content-type=multipart/*'
})
let options = {headers:headers, observer: 'response'};
const formData: FormData = new FormData();
formData.append('file', file);
//return this.http.post(this.url+'/fileUpload/upload', formData,options)
const req = new HttpRequest('POST', this.url+'/fileUpload/upload', formData, {
reportProgress: true,
responseType: 'json'
});
return this.http.request(req);
}
Java后端的控制器文件是:
@RestController
@CrossOrigin(origins = "*", allowedHeaders="*", exposedHeaders="Access-Control-Allow-Origin")
@RequestMapping("/fileUpload")
public class FileController {
private final FileService fileService;
@Autowired
public FileController(FileService fileService) {
this.fileService = fileService;
}
@PostMapping(value = "/upload")
public void handleFileUpload(@RequestParam("file") MultipartFile file) throws IOException {
fileService.storeFile(file);
}}
Java后端的服务文件是:
@Service
public class FileService {
private static final String FILE_DIRECTORY = "D:\\temp";
public void storeFile(MultipartFile file) throws IOException {
Path filePath = Paths.get(FILE_DIRECTORY + "\" + file.getOriginalFilename());
Files.copy(file.getInputStream(), filePath, StandardCopyOption.REPLACE_EXISTING);
}
}
在控制台中上传时,我可以看到文件名。此外,在请求的正文中,formData 将 xml 文件显示为 Networks 选项卡中的内容。我的 Java 控制台,我收到错误:
2020-12-15 12:26:53.144 WARN 9688 --- [nio-8080-exec-8] .w.s.m.s.DefaultHandlerExceptionResolver : Resolved [org.springframework.web.multipart.support.MissingServletRequestPartException: Required request part 'file' is not present]
前端控制台中的错误:
HttpHeaderResponse {headers: HttpHeaders, status: 400, statusText: "OK", url: "http://localhost:8080/fileUpload/upload", ok: false, …}
headers: HttpHeaders {normalizedNames: Map(0), lazyUpdate: null, lazyInit: ƒ}
ok: false
status: 400
statusText: "OK"
type: 2
url: "http://localhost:8080/fileUpload/upload"
__proto__: HttpResponseBase
我究竟做错了什么?
解决方案
您只发送文件名,而不是实际的文件 blob。
尝试进行以下更改,
组件.ts:
uploadFile() {
this.currentFile = this.fileName;
console.log(this.currentFile, this.filesToUpload[0]);
this.uploadService.uploadFile(this.currentFile, this.filesToUpload[0])
.subscribe((data) => {
console.log(data)
},
error => {
console.log(error)
});
}
服务.ts
uploadFile(fileName: string, file: File): Observable<any> {
let headers = new HttpHeaders({
'Access-Control-Allow-Origin': '*',
'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS',
'Access-Control-Allow-Headers': 'Content-Type,Accept,X-Access-Token,X-Key,Authorization,X-Requested-With,Origin,Access-Control-Allow-Origin,Access-Control-Allow-Credentials,content-type=multipart/*'
})
let options = {headers:headers, observer: 'response'};
const formData: FormData = new FormData();
formData.append('fileName', fileName);
formData.append('file', file);
const req = new HttpRequest('POST', this.url+'/fileUpload/upload', formData, {
reportProgress: true,
responseType: 'json'
});
return this.http.request(req);
}
请参阅此链接以了解更多信息formData
推荐阅读
- shell - 在ash中确定子目录是否存在但不在某个目录下
- javascript - 我无法添加第二张图片。第一个图像输入只工作
- asp.net - ASP.NET 给出 SQL Server 错误。可能是由于 SQL Server Express 上没有配置日志
- javascript - 基于 JavaScript 中另一个对象的订单对象
- javascript - Axios 中的布尔参数获取请求自动在服务器端转换为字符串
- php - PHP四舍五入有问题的小数点后三位
- envoyproxy - 各种Envoy RESPONSE_FLAGS的原因是什么
- ios - ionic 5 iOS 应用程序卡在启动画面上,没有错误日志
- python - 特定范围内所有 GPS 点的平均测量值
- c++ - 基于 C++ 范围的指针向量循环。如何通过 const 引用捕获元素?