2013-10-14 11 views
0

我想有一個在這個下跌的文件angularjs HTML5上載了的jsfiddle例如:Angular.js HTML5文件上傳到Grails的控制器

http://jsfiddle.net/danielzen/utp7j/

由一個Grails控制器上傳到後端。 在試圖做到這一點我創建了一個簡單的Grails控制器:

class UploadController { 

    def index() { 

     if (request instanceof MultipartHttpServletRequest){ 
      for(filename in request.getFileNames()){ 
       MultipartFile file = request.getFile(filename) 
       String newFileName = UUID.randomUUID().toString() + file.originalFilename.substring(file.originalFilename.lastIndexOf(".")) 
       file.transferTo(new File("/home/myuser/temp/$newFileName")) 
      } 
     } 

     render "ok" 
    } 

} 

然後我打開一個ajax XMLHttpRequest2中POST到Grails的控制器:

xhr.open("POST", "http://localhost:8080/app/upload") 

但Grails的控制器無法施展請求MultipartHttpServletRequest, 可能是因爲這個調用grails控制器的ajax方式沒有使用上傳的multipart/form-data方式。 我試着在xhr上爲ententType multipart/form-data設置標題無濟於事。

我完全被卡住的那一刻,並想知道我怎麼可以處理Grails的控制器

+0

看看裏面'params'什麼在那裏? –

回答

1

我使用內置的Chrome開發人員工具跟蹤了由XmlHttpRequest.send(formData)調用生成的POST請求。 令我驚訝的是,請求方法不是類型爲POST的enctype = multipart/form-data,而是類型爲OPTIONS的類型。

這個提示讓我走上了正確的軌道,並且在Google的幫助下,我發現這個OPTIONS請求是按照CORS定義的按照規範發生的預檢檢查。

從wikipdia:

跨域資源共享(CORS)是一種機制,允許 JavaScript的網頁上進行的XMLHttpRequest到另一個域, 不是域JavaScript的起源[1 ]這種「跨域」請求在其他情況下可能會被網頁瀏覽器禁止,即按照相同的 原始安全策略。 CORS定義了瀏覽器和服務器可以進行交互以確定是否允許交叉源請求的方式。[2]它比僅允許相同來源請求的功能更強大,但它比簡單地允許所有的 這樣的跨域請求更安全。

CORS標準通過添加新的HTTP標頭起作用,允許服務器 爲允許的原始域服務資源。瀏覽器支持這些 標題並強制執行它們建立的限制。此外,對於 可能導致對用戶數據產生副作用的HTTP請求方法(特別是對於 ,對於GET以外的HTTP方法或對於某些MIME類型的 POST使用),規範要求瀏覽器 「預檢」請求通過HTTP OPTIONS請求頭從服務器 請求支持的方法,然後在從服務器「批准」 服務器時,使用實際HTTP請求 方法發送實際請求。服務器還可以通知客戶端 (包括Cookie和HTTP驗證數據)是否應該以 請求發送「憑證」。

因爲我的Grails(Tomcat)的服務器,從本地主機上運行:8080,我的HTML/JavaScript是從WebStorm IDE中運行其內置的本地主機上的http服務器:63342,並從XmlHttpRequest有效是CORS,因爲同一主機上的不同端口號也被視爲交叉源。

因此,我需要確保Grails的(Tomcat)的服務器所允許這一點,我能夠用出色的CORS插件的Grails可以在https://github.com/davidtinker/grails-cors

被發現後,該要求是要做到這一點識別爲MultipartHttpServletRequest和文件可以取自params

0

上傳的文件在網絡採取偷看從小提琴做上傳當你:

------WebKitFormBoundarygZi30fqQLB2A9qAC 
Content-Disposition: form-data; name="uploadedFile"; filename="file.txt" 
Content-Type: text/javascript 


------WebKitFormBoundarygZi30fqQLB2A9qAC-- 

我相信,你會得到一個「UploadedFile的」爲帕拉姆鑰匙插入Grails的,所以你可以寫這樣的控制器操作:

def uploadFile(CommonsMultipartFile uploadedFile) { 
    ///accessing the file data: uploadedFile.bytes, uploadedFile.contentType, uploadedFile.originalFilename 
} 

可以肯定的是什麼正在通過對操作接收的params映射進行調試並相應地更改操作方法參數名稱。

+0

這就是預期的結果,但是由於使用XmlHttpRequest的CORS(跨源資源共享),我遇到了一個問題。查看我的答案瞭解更多詳情。 – nkr1pt

0
<body ng-controller="FileUploadCtrl"> 
$scope.selectedFile=[]; 
         $scope.onFileSelect = function ($files) { 
          $scope.uploadProgress = 0; 
          $scope.selectedFile = $files; 
         }; 
         $scope.myData = {}; 

         $scope.upload = function(){ 
          var formData = new FormData(); 
          formData.append("file", $scope.selectedFile[0]); 
          formData.append("data", myData.message.value); 
          $http.post('api/upload', formData, { 
           transformRequest: angular.identity, 
           headers: { 
            'enctype': 'multipart/form-data', 
            'Content-Type': undefined 
           } 
          }) 
          .success(function(){ 
           alert("done"); 
          }) 
          .error(function(){ 
           alert("failed"); 
        }); 


</body> 

<form ng-submit="upload()" method="post" enctype="multipart/form-data" name="myData">  <div> 

    <textarea rows="3" name="message" placeholder="Send Message"></textarea>    
      <input type="file" ng-file-select="onFileSelect($files)" /> 
     </div> 
     <button type="submit" class="btn btn-primary">upload</button> 
     </form>