AngularJS: मल्टीपार्ट फॉर्म के साथ एक साधारण फ़ाइल अपलोड कैसे लागू करें?


144

मैं AngularJS से नोड.जेएस सर्वर पर एक सरल मल्टीपार्ट फॉर्म पोस्ट करना चाहता हूं, फॉर्म में एक भाग में JSON ऑब्जेक्ट और दूसरे भाग में एक छवि होनी चाहिए, (मैं वर्तमान में केवल $ संसाधन के साथ JSON ऑब्जेक्ट पोस्ट कर रहा हूं)

मुझे लगा कि मुझे इनपुट प्रकार = "फ़ाइल" से शुरू करना चाहिए, लेकिन फिर पता चला कि AngularJS उस से बंध नहीं सकता है।

सभी उदाहरण मुझे मिल सकते हैं ड्रैग एंड ड्रॉप के लिए jQuery प्लगइन्स को लपेटने के लिए। मुझे एक फ़ाइल का एक सरल अपलोड चाहिए।

मैं AngularJS के लिए नया हूं और अपने खुद के निर्देश लिखने के साथ बिल्कुल भी सहज नहीं हूं।


1
मुझे लगता है कि इससे मदद मिल सकती है: noypi-linux.blogspot.com/2013/04/…
Noypi Gilas

1
इस उत्तर को देखें: stackoverflow.com/questions/18571001/… पहले से ही काम कर रहे सिस्टम के लिए बहुत सारे विकल्प।
एनओज

जवाबों:


188

एंगुलरज की तुलना में कोई अन्य निर्भरता वाला वास्तविक कार्य समाधान (v.1.0.6 के साथ परीक्षण किया गया)

एचटीएमएल

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

Angularjs (1.0.6) "इनपुट-फाइल" टैग पर एनजी-मॉडल का समर्थन नहीं करते हैं, इसलिए आपको इसे "मूल-मार्ग" में करना होगा जो उपयोगकर्ता से सभी (अंततः) चयनित फ़ाइलों को पास करता है।

नियंत्रक

$scope.uploadFile = function(files) {
    var fd = new FormData();
    //Take the first selected file
    fd.append("file", files[0]);

    $http.post(uploadUrl, fd, {
        withCredentials: true,
        headers: {'Content-Type': undefined },
        transformRequest: angular.identity
    }).success( ...all right!... ).error( ..damn!... );

};

शांत भाग अपरिभाषित सामग्री-प्रकार और ट्रांसफ़ॉर्मेंस है: angular.identity जो $ http पर सही "सामग्री-प्रकार" चुनने और मल्टीपार्ट डेटा को संभालने के लिए आवश्यक सीमा का प्रबंधन करने की क्षमता देता है।


2
@ फैबियो क्या आप मुझे समझा सकते हैं कि यह ट्रांसफॉर्मर क्या करता है? कोणीयता क्या है? मैं सिर्फ मल्टीपार्ट फाइल अपलोड को पूरा करने के लिए दिन भर अपना सिर पीट रहा था।
अगस्त

1
@RandomUser एक जावा रेस्ट एप्लीकेशन में, कुछ इस तरह mkyong.com/webservices/jax-rs/file-upload-example-in-jersey
Fabio Bonfante

2
वाह, बस शानदार, बहुत बहुत धन्यवाद। यहाँ मुझे कई चित्र और कुछ अन्य डेटा अपलोड करने हैं और साथ ही मैं fd को मैनिप्युलेट करता fd.append("file", files[0]); fd.append("file",files[1]); fd.append("name", "MyName")
हूं

1
कंसोल। flog (fd) दिखाता है कि फॉर्म खाली है? क्या यह ऐसा है?
जे बॉर्न

4
ध्यान दें कि यह काम नहीं करेगा यदि आपके पास डिबगइन्फो अक्षम है (जैसा कि अनुशंसित है)
ब्रूनो

42

आप सरल / हल्के एनजी फ़ाइल अपलोड निर्देश का उपयोग कर सकते हैं । यह फाइलएपीआई फ्लैश शिम के साथ नॉन-एचटीएमएल 5 ब्राउजर के लिए ड्रैग एंड ड्रॉप, फाइल प्रोग्रेस और फाइल अपलोड का समर्थन करता है

<div ng-controller="MyCtrl">
  <input type="file" ngf-select="onFileSelect($files)" multiple>
</div>

जे एस:

//inject angular file upload directive.
angular.module('myApp', ['ngFileUpload']);

var MyCtrl = [ '$scope', 'Upload', function($scope, Upload) {
  $scope.onFileSelect = function($files) {
  Upload.upload({
    url: 'my/upload/url',
    file: $files,            
  }).progress(function(e) {
  }).then(function(data, status, headers, config) {
    // file is uploaded successfully
    console.log(data);
  }); 

}];

क्या यह एक बार में प्रत्येक फ़ाइल के लिए एक एकल पोस्ट अनुरोध नहीं कर रहा है?
एनॉयज़

हाँ यह करता है। जीथब इश्यू ट्रैकर में चर्चा है कि एक-एक करके फाइल अपलोड करना बेहतर क्यों है। फ्लैश एपीआई एक साथ फाइल भेजने का समर्थन नहीं करता है और AFAIK अमेज़न S3 इसका समर्थन नहीं करता है।
डैनियल

तो, आप कह रहे हैं कि सामान्य अधिक सही दृष्टिकोण एक बार में एक फ़ाइल POST अनुरोध भेज रहा है? मैं इसमें कई फायदे देख सकता हूं, लेकिन सर्वर-साइड रेस्टफुल सपोर्ट बनाते समय और भी परेशानी।
अनॉयज

2
जिस तरह से मैं इसे लागू करता हूं वह प्रत्येक फाइल को एक संसाधन के रूप में अपलोड करने के लिए है और सर्वर इसे स्थानीय फ़ाइल सिस्टम (या डेटाबेस) पर बचाएगा और उस फ़ाइल के लिए एक अद्वितीय आईडी (यानी यादृच्छिक फ़ोल्डर / फ़ाइल नाम या डीबी आईडी) लौटाएगा। फिर एक बार सभी अपलोड हो जाने के बाद, क्लाइंट एक और PUT / POST अनुरोध भेजता है जो इस अनुरोध के लिए अपलोड की गई फ़ाइलों का अतिरिक्त डेटा और आईडी है। फिर सर्वर संबंधित फ़ाइलों के साथ रिकॉर्ड को बचाएगा। यह जीमेल की तरह है जब आप फाइलें अपलोड करते हैं और फिर ईमेल भेजते हैं।
डैनियल

1
यह "सरल / हल्का" नहीं है। नमूने अनुभाग में केवल एक फ़ाइल अपलोड करने का उदाहरण नहीं है।
क्रिस

9

सीधे फ़ाइल भेजना अधिक कुशल है।

बेस 64 एन्कोडिंग की Content-Type: multipart/form-dataएक अतिरिक्त 33% भूमि के ऊपर कहते हैं। यदि सर्वर इसका समर्थन करता है, तो फाइलों को सीधे भेजना अधिक कुशल है:

$scope.upload = function(url, file) {
    var config = { headers: { 'Content-Type': undefined },
                   transformResponse: angular.identity
                 };
    return $http.post(url, file, config);
};

फ़ाइल ऑब्जेक्ट के साथ POST भेजते समय , इसे सेट करना महत्वपूर्ण है 'Content-Type': undefinedएक्सएचआर भेजने विधि तो पता लगा लेगा फ़ाइल वस्तु और स्वचालित रूप से सामग्री प्रकार निर्धारित किया है।

कई फाइलें भेजने के लिए, एक फाइललिस्ट से सीधे कई अनुरोध करना देखें$http.post


मुझे लगा कि मुझे इनपुट प्रकार = "फ़ाइल" से शुरू करना चाहिए, लेकिन फिर पता चला कि AngularJS उस से बंध नहीं सकता है।

<input type=file>तत्व के साथ डिफ़ॉल्ट रूप से काम नहीं करता है एनजी मॉडल के निर्देश । इसे एक कस्टम निर्देश की आवश्यकता है :

"सिलेक्ट-एनजी-फाइल्स" का वर्किंग डेमो जो 1 के साथ काम करता हैng-model

angular.module("app",[]);

angular.module("app").directive("selectNgFiles", function() {
  return {
    require: "ngModel",
    link: function postLink(scope,elem,attrs,ngModel) {
      elem.on("change", function(e) {
        var files = elem[0].files;
        ngModel.$setViewValue(files);
      })
    }
  }
});
<script src="//unpkg.com/angular/angular.js"></script>
  <body ng-app="app">
    <h1>AngularJS Input `type=file` Demo</h1>
    
    <input type="file" select-ng-files ng-model="fileArray" multiple>
    
    <h2>Files</h2>
    <div ng-repeat="file in fileArray">
      {{file.name}}
    </div>
  </body>


$http.post सामग्री प्रकार के साथ multipart/form-data

अगर किसी को भेजना है multipart/form-data:

<form role="form" enctype="multipart/form-data" name="myForm">
    <input type="text"  ng-model="fdata.UserName">
    <input type="text"  ng-model="fdata.FirstName">
    <input type="file"  select-ng-files ng-model="filesArray" multiple>
    <button type="submit" ng-click="upload()">save</button>
</form>
$scope.upload = function() {
    var fd = new FormData();
    fd.append("data", angular.toJson($scope.fdata));
    for (i=0; i<$scope.filesArray.length; i++) {
        fd.append("file"+i, $scope.filesArray[i]);
    };

    var config = { headers: {'Content-Type': undefined},
                   transformRequest: angular.identity
                 }
    return $http.post(url, fd, config);
};

FormData API के साथ POST भेजते समय , इसे सेट करना महत्वपूर्ण है 'Content-Type': undefinedएक्सएचआर भेजने विधि तो पता लगा लेगा FormDataवस्तु और स्वचालित रूप से करने के लिए सामग्री प्रकार हैडर सेट बहुखण्डीय / फार्म-डेटा के साथ उचित सीमा


filesInputनिर्देश कोणीय 1.6.7 के साथ काम करने प्रकट नहीं होता है, मैं में फ़ाइलों को देख सकते ng-repeat, लेकिन एक ही $scope.variableनियंत्रक में खाली है? इसके अलावा आपके एक उदाहरण का उपयोग करता है file-modelऔर एकfiles-input
Dan

@ क्या मैंने इसका परीक्षण किया है और यह काम करता है। यदि आपको अपने कोड में कोई समस्या है, तो आपको एक न्यूनतम, पूर्ण, सत्यापन योग्य उदाहरण के साथ एक नया प्रश्न पूछना चाहिए । को निर्देश नाम बदल दिया select-ng-files। AngularJS 1.7.2 के साथ परीक्षण किया गया।
georgeawg

5

मेरा बस यही मुद्दा था। इसलिए कुछ दृष्टिकोण हैं। पहला यह है कि नए ब्राउज़र समर्थन करते हैं

var formData = new FormData();

इस ब्लॉग के लिंक का अनुसरण करें कि कैसे आधुनिक ब्राउज़रों तक समर्थन सीमित है, लेकिन अन्यथा यह इस समस्या को पूरी तरह हल करता है।

अन्यथा आप लक्ष्य विशेषता का उपयोग करके प्रपत्र को एक iframe पर पोस्ट कर सकते हैं। जब आप फॉर्म पोस्ट करते हैं, तो सुनिश्चित करें कि लक्ष्य को iframe पर सेट किया जाना चाहिए, जिसकी प्रदर्शन संपत्ति किसी के पास नहीं है। लक्ष्य iframe का नाम है। (बस तुम इतना जानते हो।)

आशा है कि ये आपकी मदद करेगा


AFAIK FormData IE के साथ काम नहीं करता है। शायद इसका एक बेहतर विचार छवि फ़ाइल के base64 एन्कोडिंग करना और JSON में भेजना है? मैं चुने हुए फ़ाइल पथ को प्राप्त करने के लिए AngularJS के साथ इनपुट प्रकार = "फ़ाइल" से कैसे जुड़ सकता हूं?
गैल बेन-हैम

3

मुझे पता है कि यह एक देर से प्रवेश है लेकिन मैंने एक सरल अपलोड निर्देश बनाया है। जिसे आप कुछ ही समय में काम कर सकते हैं!

<input type="file" multiple ng-simple-upload web-api-url="/api/post"
       callback-fn="myCallback" />

वेब एपीआई का उपयोग करके जीथब पर एनजी-सिंपल-अपलोड अधिक।


2
ईमानदार होना, अपने प्रोजेक्ट रीडमी में कॉपी-पेस्ट कोड का सुझाव देना एक बड़ा काला निशान हो सकता है। एनपीएम या बोवर जैसे सामान्य पैकेज प्रबंधकों के साथ अपनी परियोजना को एकीकृत करने का प्रयास करें।
स्टेफानो टॉरेसी

2

आप $resourceडेटा को असाइन करके अपलोड कर सकते हैं actionsजैसे कि संसाधन की विशेषता

$scope.uploadFile = function(files) {
    var fdata = new FormData();
    fdata.append("file", files[0]);

    $resource('api/post/:id', { id: "@id" }, {
        postWithFile: {
            method: "POST",
            data: fdata,
            transformRequest: angular.identity,
            headers: { 'Content-Type': undefined }
        }
    }).postWithFile(fdata).$promise.then(function(response){
         //successful 
    },function(error){
        //error
    });
};

1

मैंने बस एक साधारण निर्देश (मौजूदा एक टोके से) को AngularJs में एक साधारण अपलोडर के लिए लिखा था।

(सटीक jQuery अपलोडर प्लगइन https://github.com/blueimp/jQuery-File-Upload है )

AngularJs (CORS कार्यान्वयन के साथ) का उपयोग कर एक साधारण अपलोडर

(यद्यपि सर्वर पक्ष PHP के लिए है, आप इसे नोड में भी सरल रूप से बदल सकते हैं)


1
यह उल्लेख करना न भूलें कि आप अपने रेपो के मुद्दों पर प्रतिक्रिया देने के लिए कोई समय नहीं देते हैं
ओलेग बेलौसोव

@OlegTikhonov: हाँ, गंभीरता से कुछ अन्य परियोजनाओं के साथ अटक गया। शायद ही कोई ध्यान दे पाए।
sk8terboi87 ツ
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.