2015-06-01 12 views
6

Ciągle nie rozumiem innej metody przesyłania plików. Serwer zaplecza nie jest pod moją kontrolą, ale mogę przesłać plik za pomocą strony Swagger lub Listonosza. Oznacza to, że serwer działa poprawnie. Ale kiedy używam AngularJS do przesyłania, to nie działa.Wysyłaj wieloczęściowe dane formularzy z nazwą pliku w polu Request Payload

Oto, co działa za pomocą Postman do testowania. Jestem po prostu za pomocą form-data:

enter image description here

Wskazówka, że ​​wniosek ma nagłówków Content-Type jako multipart/form-data. Jednak Request Payload ma filename i Content-Type jako image/png.

Oto mój kod:

$http({ 
    method: 'POST', 
    url: ApiUrlFull + 'Job/Item?smartTermId=0&name=aaa1&quantity=1&ApiKey=ABC', 
    headers: { 'Content-Type': undefined }, 
    transformRequest: function(data) { 
    var fd = new FormData(); 
    fd.append('file', params.imageData); 
    return fd; 
    } 
}) 

params jest tylko obiekt z pliku url w imageData.

Mój kod wysyła również podobne parametry adresu URL (dzięki czemu możemy zignorować ten problem). Ale Request Payload jest base64 i wygląda inaczej, ponieważ brakuje pola filename.

enter image description here

Mam zerową kontrolę backend i to jest napisane w .NET.

Więc domyślam się, że moje pytanie brzmi: używając Angular (albo http, albo zasobu), w jaki sposób mogę zmodyfikować żądanie tak, że wysyłam poprawne żądanie ładunku, jak robi to Postman? Nie mogę wymyślić, jak to odwrócić.

Próbowałem tego https://github.com/danialfarid/ng-file-upload i rzeczywiście wykonałem polecenie OPCJE przed POST (zakładając wydanie CORS). Ale serwer dał błąd 405 dla OPCJE.

+0

Aby wysłać efekt w pierwszym żądaniu, potrzebny jest właściwy obiekt 'Plik' (lub tylko' Blob'), a parametr 'params.imageData' jest łańcuchem znaków. – Musa

+0

'params.imageData' to po prostu' file: // 'URL z' input type = file'. Czy masz na myśli coś jeszcze, o czym nie myślę? –

+0

Z tego co napisałeś 'params.imageData' jest zakodowany w base64 png, który jest łańcuchem. Aby uzyskać FormData do publikowania danych w taki sposób, jak chcesz, musi to być obiekt File lub obiekt Blob. I'fd.append ('file', blob_from_imageData); 'szukaj SO dla pytania, aby przekonwertować URL danych na obiekt typu blob. – Musa

Odpowiedz

1

Można użyć coś wzdłuż linii:

<input type="file" name="file" onchange="uploadFile(this.files)"/> 

I w kodzie:

$scope.uploadFile = function(files) { 
    var fd = new FormData(); 
    //Take the first selected file 
    fd.append("file", files[0]); 
    var uploadUrl = ApiUrlFull + 'Job/Item?smartTermId=0&name=aaa1&quantity=1&ApiKey=ABC'; 
    $http.post(uploadUrl, fd, { 
     withCredentials: true, 
     headers: {'Content-Type': undefined }, 
     transformRequest: angular.identity 
    }).success(...all right!...).error(..damn!...); 

}; 
0

moją potrzebę był następujący.

  • W formularzu znajduje się domyślny obraz.
  • Kliknięcie na zdjęcie otwiera okno wyboru pliku.
  • Gdy użytkownik wybierze plik, zostanie natychmiast przesłany do serwera.
  • Gdy tylko otrzymam odpowiedź, że plik jest prawidłowy, wyświetl obraz użytkownikowi zamiast domyślnego obrazu i dodaj przycisk usuwania obok niego.
  • Jeśli użytkownik kliknie istniejący obraz, okno wyboru pliku zostanie ponownie otwarte.

Próbowałem użyć kilka fragmentów kodu na github, że nie rozwiąże problemu, ale prowadził mnie w odpowiedni sposób, a co skończyło się tak, jak robi to:

dyrektywa

angular.module("App").directive('fileModel', function ($parse) { 
    return { 
     restrict: 'A', 
     link: function (scope, element, attrs) { 
      scope.files = {}; 
      var model = $parse(attrs.fileModel); 
      var modelSetter = model.assign; 

      // I wanted it to upload on select of file, and display to the user. 
      element.bind('change', function() { 
       scope.$apply(function() { 
        modelSetter(scope, element[0].files[0]); 
       }); 

       // The function in the controller that uploads the file. 
       scope.uploadFile(); 
      }); 
     } 
    }; 
}); 

Html

<div class="form-group form-md-line-input"> 
    <!-- A remove button after file has been selected --> 
    <span class="icon-close pull-right" 
      ng-if="settings.profile_picture" 
      ng-click="settings.profile_picture = null"></span> 
    <!-- Show the picture on the scope or a default picture --> 
    <label for="file-pic"> 
     <img ng-src="{{ settings.profile_picture || DefaultPic }}" 
      class="clickable" width="100%"> 
    </label> 

    <!-- The actual form field for the file --> 
    <input id="file-pic" type="file" file-model="files.pic" style="display: none;" /> 
</div> 

Controller

$scope.DefaultPic = '/default.png'; 

$scope.uploadFile = function (event) { 
     var filename = 'myPic'; 
     var file = $scope.files.pic; 
     var uploadUrl = "/fileUpload"; 

     file('upfile.php', file, filename).then(function (newfile) { 
      $scope.settings.profile_picture = newfile.Results; 
      $scope.files = {}; 
     }); 
}; 

function file(q, file, fileName) { 
    var fd = new FormData(); 
    fd.append('fileToUpload', file); 
    fd.append('fn', fileName); 
    fd.append('submit', 'ok'); 

    return $http.post(serviceBase + q, fd, { 
     transformRequest: angular.identity, 
     headers: { 'Content-Type': undefined } 
    }).then(function (results) { 
     return results.data; 
    }); 
} 

Nadzieję, że to pomaga.

P.S. Z tego przykładu było dużo kodu, jeśli potrzebujesz wyjaśnienia, po prostu komentarz.

Powiązane problemy