将文件上传到Spring时,我收到400(错误请求)。
上传在邮递员上运行正常但在Angular2上效果不错。
这是邮递员代码。工作得很好.. 我使用了基本身份验证和用户名+密码
-buildpath
这是我的Spring Controller。它很简单,获取文件并将其保存到磁盘。
var data = new FormData();
data.append("uploadfile", "pasta2.zip");
var xhr = new XMLHttpRequest();
xhr.withCredentials = true;
xhr.addEventListener("readystatechange", function () {
if (this.readyState === 4) {
console.log(this.responseText);
}
});
xhr.open("POST", "http://localhost:8080/api/uploadFile");
xhr.setRequestHeader("authorization", "Basic b3BlcmF0aW9uczpvcGVyYXRpb25z");
xhr.setRequestHeader("cache-control", "no-cache");
xhr.setRequestHeader("postman-token", "59d5ebf2-6039-e924-1550-c96e491f97ee");
xhr.send(data);
这是我的Angular2: 上面的代码更多。如果您需要,我可以提供。
@RestController
public class uploadFile {
private Logger logger = LoggerFactory.getLogger(this.getClass());
public String filenameZip, directoryZip;
@RequestMapping(value = "/api/uploadFile", method = RequestMethod.POST)
@ResponseBody
public ResponseEntity<?> uploadFile(
@ModelAttribute("uploadfile") MultipartFile uploadfile) {
try {
// Get the filename and build the local file path (be sure that the
// application have write permissions on such directory)
String filename = uploadfile.getOriginalFilename();
String directory = "C://Develop//files";
String filepath = Paths.get(directory, filename).toString();
filenameZip = "c:/Develop/files/"+filename;
directoryZip = "c:/Develop/files";
// Save the file locally
BufferedOutputStream stream =
new BufferedOutputStream(new FileOutputStream(new File(filepath)));
stream.write(uploadfile.getBytes());
stream.close();
} catch (Exception e) {
System.out.println(e.getMessage());
return new ResponseEntity<>(HttpStatus.BAD_REQUEST);
}
unzip(filenameZip, directoryZip);
return new ResponseEntity<>(HttpStatus.OK);
} // method uploadFile
从我的App上传文件时弹簧的日志:
/**
* File upload
* Upload a Zip file to server.
*/
filesToUpload: Array<File>;
/**
* FormData gets the file as an Object and Post it on xhr with Auth
* Upload a Zip file to server.
*/
upload() {
this.makeFileRequest("http://localhost:8080/api/uploadFile", [], this.filesToUpload).then((result) => {
console.log(result);
}, (error) => {
console.error(error);
});
}
fileChangeEvent(fileInput: any){
this.filesToUpload = <Array<File>> fileInput.target.files;
}
makeFileRequest(url: string, params: Array<string>, files: Array<File>) {
return new Promise((resolve, reject) => {
var formData: any = new FormData();
var xhr = new XMLHttpRequest();
for(var i = 0; i < files.length; i++) {
formData.append("uploads[]", files[i], files[i].name);
}
xhr.onreadystatechange = function () {
if (xhr.readyState == 4) {
if (xhr.status == 200) {
resolve(JSON.parse(xhr.response));
} else {
reject(xhr.response);
}
}
}
xhr.open("POST", url, true);
/**
* Must set the Authorization or the Spring MVC does not accept the request. Tested on Postman
*/
xhr.setRequestHeader('Authorization', 'Basic ' + btoa("operations" + ":" + "operations"));
xhr.withCredentials = true;
xhr.send(formData); //Form data is sent to Spring
});
}
使用Postman应用程序时Spring的日志:
2016-11-27 19:14:57.862 INFO 3596 --- [io-8080-exec-10] o.e.ws.service.AccountServiceBean : > findByUsername
2016-11-27 19:14:57.875 INFO 3596 --- [io-8080-exec-10] o.e.ws.service.AccountServiceBean : < findByUsername
2016-11-27 19:14:57.986 INFO 3596 --- [io-8080-exec-10] o.s.b.a.audit.listener.AuditListener : AuditEvent [timestamp=Sun Nov 27
19:14:57 UTC 2016, principal=operations, type=AUTHENTICATION_SUCCESS, data={details=org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null}]
null
在Chrome上,它说:
2016-11-27 19:16:12.762 INFO 3596 --- [nio-8080-exec-1] o.e.ws.service.AccountServiceBean : > findByUsername
2016-11-27 19:16:12.851 INFO 3596 --- [nio-8080-exec-1] o.e.ws.service.AccountServiceBean : < findByUsername
2016-11-27 19:16:12.965 INFO 3596 --- [nio-8080-exec-1] o.s.b.a.audit.listener.AuditListener : AuditEvent [timestamp=Sun Nov 27
19:16:12 UTC 2016, principal=operations, type=AUTHENTICATION_SUCCESS, data={details=org.springframework.security.web.authentication.WebAuthenticationDetails@b364: RemoteIpAddress: 0:0:0:0:0:0:0:1; SessionId: null}]
Unzipping to c:\Develop\files\pasta2\dsa.txt
我认为这不是发送带有请求的zip文件。
答案 0 :(得分:1)
既然你可以通过Postman完成你想要的东西,我可以放心地假设你的问题不在后端。 问题是您没有在请求中附加任何Multipart文件,位于前端(代码的Angular部分)。
操作XHR请求是一种粗略的方法,从Angular的最终版本开始就不需要这样做。
执行此操作的好方法是创建专用服务以执行文件上载:
import { Injectable } from '@angular/core';
import {Http, Headers, Response} from '@angular/http';
import 'rxjs/add/operator/map';
@Injectable()
export class UploadService {
//Import your APIs endpoint
private url = AppSettings.API_ENDPOINT;
constructor(private http:Http) { }
upload(files:FileList){
var formData = new FormData();
if(files.length > 0){
for(var i = 0; i < files.length; i++){
formData.append("uploadfile", files[i]);
}
return this.http
.post(this.url + '/api/upload', formData)
}
}
}
然后只需订阅组件中的服务
uploadDocs($event:any){
console.log("IMPORT")
var files:any = $event.target.files;
console.log(files);
this.uploadService.uploadLibraries(files)
.subscribe(data => this.successImport(data),
error => this.failImport(error));
}