java - Spring 和 Angular2 400(错误请求)

标签 java spring spring-mvc angular

将文件上传到 Spring 时,我收到此 400(错误请求)。

上传在 postman 上运行良好,但在 Angular2 上则不太好。

这是 postman 代码。工作得很好.. 我使用基本身份验证和用户名+密码

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);

这是我的 Spring Controller 。它简单地获取文件并将其保存到磁盘。

@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

这是我的 Angular2: 上面是更多代码。如果你需要我可以提供。

/**
 * 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
    });
}

当我从我的应用程序上传文件时来自 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

当我使用 Postman 应用程序时来自 Spring 的日志:

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

在 Chrome 上,它显示:

zone.js:1382 POST http://localhost:8080/api/uploadFile 400 (Bad Request)

我相信这不会随请求一起发送 zip 文件。

最佳答案

既然你可以通过 Postman 完成你想要的事情,我可以有把握地假设你的问题不在后端。 问题是您没有在前端的请求中附加任何多部分文件(代码的 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));
}

关于java - Spring 和 Angular2 400(错误请求),我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/40832985/

相关文章:

java - 带有测试 Spring Boot 的 Gradle fat jar 的 NoClassDefFoundError

Spring DATA REST - 如何使用默认的 spring 实现将实体转换为自定义 Controller 中的资源

spring - 在 weblogic 10.3.6 中部署 Spring 4.1.6 mvc webapp

java - 如何在 Spring Security MVC 中编写简单的过滤器?

java - RxJava- 在 Observable 链中执行 peek() 或 void 操作?

java - 类无法解析为类型

java - 访问使用 POSTMAN 运行良好的 Web API 时出错

java - 保存实体时出现 ConcurrentModificationException

java - 如何使用 Spring Data REST 在 OneToMany 关系中添加对象

java - 如何在log4j中禁用DEBUG?