Spring和Angular2 400(错误请求)

时间:2016-11-27 19:27:27

标签: java spring spring-mvc angular

将文件上传到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文件。

1 个答案:

答案 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));
}