2016-08-28 3 views
4

Ich benutze ng-file-upload in Angular auf Client-Seite, um eine Datei (Bild, Text usw.) an Spring Boot-Anwendung zu senden.POST Anfrage mit mehrteiligen Daten im Frühjahr mvc

Ich habe Client-Seite in Xampp mit URL "Localhost" ausgeführt, während Spring-Instanz separat mit URL "Localhost: 8080" .Cors auf beiden Seiten aktiviert sind und alle anderen Anforderungen erfolgreich unterhalten werden.

Client Side-Code:

 Upload.upload({ 
     url: 'http://localhost:8080/file/upload', 
     method:'POST', 
      data: { 
      uploadedPicture: file, 
      uploadedFrom: 'recipe' 
     }, 
    }).then(function(response) { 
     $timeout(function() { 
      $scope.result = response.data; 
     }); 
    }, function(response) { 
     if (response.status > 0) $scope.errorMsg = response.status + ': ' + response.data; 
    }, function(evt) { 
     $scope.progress = parseInt(100.0 * evt.loaded/evt.total); 
    }); 

Server Side-Code:

@CrossOrigin 
@RequestMapping(method = RequestMethod.POST, value = "/file/upload") 
public String handleFileUpload(@RequestParam("file") MultipartFile file, 
           RedirectAttributes redirectAttributes) { 
    if (!file.isEmpty()) { 
     try { 
      Files.copy(file.getInputStream(), Paths.get(ROOT, file.getOriginalFilename())); 
      redirectAttributes.addFlashAttribute("message", 
        "You successfully uploaded " + file.getOriginalFilename() + "!"); 
     } catch (IOException|RuntimeException e) { 
      redirectAttributes.addFlashAttribute("message", "Failued to upload " + file.getOriginalFilename() + " => " + e.getMessage()); 
     } 
    } else { 
     redirectAttributes.addFlashAttribute("message", "Failed to upload " + file.getOriginalFilename() + " because it was empty"); 
    } 

    return "redirect:/"; 
} 

ich die cors aus demselben Code Erhaltungs-Anforderungs versucht haben, mit get-Methode auf die gleiche Ressource durch das Senden der funktioniert. Aber wenn ich Post-Anfrage mit einem mehrteiligen Formular Daten (Bild oder eine andere Datei) senden, lehnt es die OPTIONS-Anfrage ab.

OPTIONS http://localhost:8080/file/upload 
    XMLHttpRequest cannot load http://localhost:8080/file/upload. Response to preflight request doesn't pass access control check: No 'Access-Control-Allow-Origin' header is present on the requested resource. Origin 'http://localhost' is therefore not allowed access. The response had HTTP status code 403. 

Ich habe diese Ressource von Postman auch getestet und es hochgeladen Datei ohne Fehler.

EDIT:Ich habe versucht, durch die http auf https ändern und es wird der Fehler als OPTIONS https://localhost:8080/file/upload net geben :: ERR_TIMED_OUT_ Problem gleiche ist, wie es nicht die erforderliche Ressource

irgendwelche Gedanken über diese finden Problem??

+0

müssen Sie den 'Access-Control-Allow-Origin'-Header auf die serverseitige Antwort setzen. Vielleicht können Sie es tun, indem Sie der Annotation "@ CrossOrigin" entsprechende Parameter hinzufügen (die damit nicht vertraut sind). Die lustige Sache ist, in Bezug auf Cross-Herkunft, verschiedene Port (8080) wird als unterschiedliche Host (Ihre Anfrage scheint von Port 80 zu kommen) – JohnnyAW

+0

Erstens, es ist ein Fall, dass die Anfrage von einem anderen Port ist.Es kann von einem sein andere System/Domäne, die in Zukunft der Fall sein wird. Zweitens habe ich versucht @ CrossOrigin (Ursprung = "http: // localhost"), aber das gleiche Problem.Und es ist nur mit POST-Anfrage GET funktioniert. –

+0

wie ich schon sagte, wird der andere Port als eine andere Domäne für CORS betrachtet, deshalb brauchen Sie den 'Access-Control-Allow-Origin'-Header in der Antwort. Versuchen Sie "*" als Ursprung, um jeden Ursprung zuzulassen. Andernfalls könnten Sie diesen Header selbst hinzufügen. Übrigens. Sie erhalten 403 für Statuscode, überprüfen Sie Ihre Sicherheitseinstellungen, vielleicht benötigen Sie andere Berechtigungen für den Zugriff auf diese Ressource. – JohnnyAW

Antwort

0

diese Erweiterung in Chrom versuchen, kann es Sie mit dem Sicherheitseinstellungen Problem helfen

https://chrome.google.com/webstore/detail/allow-control-allow-origi/nlfbmbojpeacfghkpbjhddihlkkiljbi?hl=fr

+1

Diese Erweiterung hilft nur bei Anfragen von meinem Browser, während ich dies für Kunden vorbereiten muss. –

+0

versuchen Sie dies https://spring.io/guides/gs/rest-service-cors/ –

+0

können Sie überprüfen code.i haben die gleiche Ressource versucht. –

0

Prüfen Sie zuerst, da Sie offensichtlich 403 als Statuscode erhalten. Vielleicht verursacht deine Umleitung am Ende Probleme, versuch es ohne.

Hier ist ein Codebeispiel, war ich vor einer Weile mit CORS-Header hinzufügen:

@RequestMapping(value="/GetSomething", method = RequestMethod.GET, produces = "application/json;charset=UTF-8") 
public ResponseEntity<String> getSomething() throws IOException { 
    HttpHeaders responseHeaders = new HttpHeaders(); 
    //need for cross-domain requests 
    responseHeaders.add("Access-Control-Allow-Origin", "*"); 
    //this one is needed, if your browser should send cookies 
    responseHeaders.add("Access-Control-Allow-Credentials", "true"); 
    ... 
    responseHeaders.setContentLength(resp.getBytes("UTF-8").length); 
    return new ResponseEntity<String>(resp, responseHeaders, HttpStatus.OK); 
} 

EDIT: entfernt Session-Parameter

EDIT2: können Sie überprüfen, ob der Code in Ihrem POST-Anfrage wird tatsächlich ausgeführt? Machen Sie einige Protokolle in der Funktion. Wenn Ihr Code nicht ausgeführt wird, haben Sie eindeutig Probleme mit der Sicherheitseinrichtung und Ihre Anfrage wird nicht durch die Sicherheitsschicht geleitet. CORS ist Client-basierte Funktionalität, es kann nur Daten blockieren, NACHDEM der Browser sie vom Server bekommt!

+0

Entfernen der Umleitung war nicht hilfreich. –

+0

hast du deine Sicherheitseinstellungen überprüft? 403 bedeutet, dass du keine Erlaubnis hast, diese Ressource zu sehen !!! – JohnnyAW

+0

überprüfen Sie es durch Senden von Anfrage vom Briefträger zu dieser Ressource funktioniert es gut. –

0

Ich hatte dieses Problem zuvor in meinem aktuellen Projekt konfrontiert, nach einer Menge RND und einige Experimente, habe ich festgestellt, dass das Problem mit dem Inhaltstyp war, wann immer es ein Bild hochladen wird ein Platz zum Hochladen von Inhaltstyp ist Wichtig ist hier viel.

Ich habe dies nicht testen, aber lassen Sie mich wissen, nachdem versuchen, dies durch in der Nähe in Ihrem Code ersetzen ...

  var fd = new FormData(); 
      fd.append('uploadedPicture', file); 
      fd.append('uploadedFrom', 'recipe'); 

      Upload.upload({ 
       url: 'http://localhost:8080/file/upload', 
       method: 'POST', 
       data: fd, 
       transformRequest: angular.identity, 
       headers: {'Content-Type': undefined}, 
      }).then(function (response) { 
       $timeout(function() { 
        $scope.result = response.data; 
       }); 
      }, function (response) { 
       if (response.status > 0) 
        $scope.errorMsg = response.status + ': ' + response.data; 
      }, function (evt) { 
       $scope.progress = parseInt(100.0 * evt.loaded/evt.total); 
      }); 

Lassen Sie mich bitte wissen, danach versuchen.

0

Es macht keinen Sinn, eine Weiterleitung von einem Ajax-Aufruf zurückzugeben. Stellen Sie zunächst fest, ob das Problem mit dem Formularpost oder mit der nachfolgenden Aktion verbunden ist.Um sie ändern, so der Controller wie folgt:

@CrossOrigin 
@RequestMapping(method = RequestMethod.POST, value = "/file/upload") 
@ResponseBody 
public String handleFileUpload(@RequestParam("file") MultipartFile file) { 

    String status = null; 

    if (!file.isEmpty()) { 
     try { 
      Files.copy(file.getInputStream(), Paths.get(ROOT, file.getOriginalFilename())); 
      status = "okay"; 

     } catch (IOException|RuntimeException e) { 
      status = "error"; 
     } 
    } else { 
     status = "error"; 
    } 

    return "status"; // a literal string 
} 

Ich würde auch zur Kenntnis, dass die params von dem Front-End gesendet nicht übereinstimmen, was das Backend erwartet. Wo im Frontend geben Sie einen Parameter mit dem Namen "Datei" an, den der Controller dem angegebenen RequestParam zuordnen wird?

Die Bibliothek in Frage hat ein Ende Beispiel mit Spring MVC hier zu beenden:

https://github.com/danialfarid/ng-file-upload/wiki/spring-mvc-example

Beachten Sie, wie die Parameternamen auf beiden Seiten übereinstimmen.

2

Ein Blick auf Ihre Fehlermeldung sehe ich:

Nein "Access-Control-Allow-Origin-Header vorhanden ist

Sind Sie sicher, dass die richtigen Header hinzugefügt werden?

wir einen Filter verwendet, alle Anfragen wurden diese Header korrekt hinzugefügt, um sicherzustellen:

  • Access-Control-Allow-Origin: *
  • Access-Control-Allow-Methoden: POST, GET, OPTIONS, DELETE
  • Access-Control-Max-Alter: 3600
  • Access-Control-Allow-Header: x-requested-mit

Hier ist die Filterklasse wir sehen Sie diese Antwort

SimpleCORSFilter.java

@Component 
public class SimpleCORSFilter implements Filter { 

     public void doFilter(ServletRequest req, ServletResponse res, FilterChain chain) throws IOException, ServletException { 
      HttpServletResponse response = (HttpServletResponse) res; 
      response.setHeader("Access-Control-Allow-Origin", "*"); 
      response.setHeader("Access-Control-Allow-Methods", "POST, GET, OPTIONS, DELETE"); 
      response.setHeader("Access-Control-Max-Age", "3600"); 
      response.setHeader("Access-Control-Allow-Headers", "x-requested-with"); 
      chain.doFilter(req, res); 
     } 

     public void init(FilterConfig filterConfig) {} 

     public void destroy() {} 

    } 
1

einfach ändern @CrossOrigin Anmerkung zu: verwendet

@CrossOrigin(origins = "*", methods = {RequestMethod.POST, RequestMethod.OPTIONS}, allowedHeaders = {"Content-Type", "X-Requested-With", "accept", "Origin", "Access-Control-Request-Method", "Access-Control-Request-Headers"}, exposedHeaders = {"Access-Control-Allow-Origin", "Access-Control-Allow-Credentials"}) 
+0

@ User786, deine GET-Anfrage hat funktioniert, weil es keine Preflight-Anfrage für GETs gibt. Da Sie posten möchten, wird Ihr Browser eine OPTIONS-Anfrage stellen und Ihr Server muss dies akzeptieren und darauf reagieren. Das ist es, was '@ CrossOrigin' tun soll, und das hinzugefügte Info-Joojic scheint in deinem Kontext benötigt zu werden. –

Verwandte Themen