मैं JS fetch API के साथ फ़ाइल कैसे अपलोड करूं?


170

मैं अभी भी इसके चारों ओर अपना सिर लपेटने की कोशिश कर रहा हूं।

मैं उपयोगकर्ता को फ़ाइल इनपुट के साथ फ़ाइल (या कई भी) का चयन कर सकता हूं:

<form>
  <div>
    <label>Select file to upload</label>
    <input type="file">
  </div>
  <button type="submit">Convert</button>
</form>

और मैं submitइवेंट का उपयोग करके पकड़ सकता हूं <fill in your event handler here>। लेकिन एक बार जब मैं करता हूं, तो मैं फ़ाइल का उपयोग कैसे करूं fetch?

fetch('/files', {
  method: 'post',
  // what goes here? What is the "body" for this? content-type header?
}).then(/* whatever */);

1
आधिकारिक दस्तावेज़ कुछ जवाबों की कोशिश करने के बाद मेरे लिए काम करता है: डेवलपर .mozilla.org/en-US/docs/Web/API/Fetch_API/…, कुछ पुष्टि कर सकता है: 1. FromData में रैप फाइल की जरूरत है; 2. Content-Type: multipart/form-dataअनुरोध हैडर घोषित करने की आवश्यकता नहीं है
Spark.Bao

जवाबों:


127

यह टिप्पणियों के साथ एक मूल उदाहरण है। uploadसमारोह के लिए आप क्या देख रहे है:

// Select your input type file and store it in a variable
const input = document.getElementById('fileinput');

// This will upload the file after having read it
const upload = (file) => {
  fetch('http://www.example.net', { // Your POST endpoint
    method: 'POST',
    headers: {
      // Content-Type may need to be completely **omitted**
      // or you may need something
      "Content-Type": "You will perhaps need to define a content-type here"
    },
    body: file // This is your file object
  }).then(
    response => response.json() // if the response is a JSON object
  ).then(
    success => console.log(success) // Handle the success response object
  ).catch(
    error => console.log(error) // Handle the error response object
  );
};

// Event handler executed when a file is selected
const onSelectFile = () => upload(input.files[0]);

// Add a listener on your input
// It will be triggered when a file will be selected
input.addEventListener('change', onSelectFile, false);

8
इस उदाहरण में सामग्री-प्रकार के शीर्षलेख क्यों शामिल हैं लेकिन फ़ॉर्च एपीआई के साथ फाइलें भेजते समय एक और उत्तर उन्हें छोड़ने के लिए कहता है? इनमें से कौनसा?
jjrabbit

12
सामग्री-प्रकार सेट न करें। मैंने इसे काम करने में बहुत समय बिताया और फिर इस लेख को यह कहा कि इसे सेट न करें। और यह काम करता है! muffinman.io/uploading-files-using-fetch-multipart-form-data
Kostiantyn

आप इस फाइल को एक्सप्रेस बैकएंड से कैसे पढ़ेंगे। चूंकि फ़ाइल को प्रपत्र डेटा के रूप में नहीं भेजा जाता है। इसके बजाय इसे केवल फ़ाइल ऑब्जेक्ट के रूप में भेजा जाता है। क्या एक्सप्रेस-फाइलअप या मुलर ऐसे पेलोड को पार करता है?
साकिब 11

221

मैंने इसे इस तरह किया है:

var input = document.querySelector('input[type="file"]')

var data = new FormData()
data.append('file', input.files[0])
data.append('user', 'hubot')

fetch('/avatars', {
  method: 'POST',
  body: data
})

16
FormDataयदि आप अपलोड कर रहे हैं तो आपको फ़ाइल की सामग्री को किसी वस्तु में लपेटने की आवश्यकता नहीं है यदि आप फ़ाइल को अपलोड कर रहे हैं (जो मूल प्रश्न चाहते हैं)। इसके पैरामीटर के रूप में ऊपर fetchस्वीकार input.files[0]करेंगे body
क्लॉस

17
यदि आपके पास फ़ाइल अपलोड को संभालने वाला एक PHP बैकएंड है, तो आप फ़ाइल को फॉर्मडाटा में लपेटना चाहेंगे ताकि $ _FILES सरणी ठीक से आबाद हो।
ddelrio1986

2
मैंने यह भी देखा कि Google Chrome किसी कारण से फॉर्मडैट भाग के बिना अनुरोध पेलोड में फ़ाइल नहीं दिखाएगा। Google Chrome के नेटवर्क पैनल में एक बग जैसा लगता है।
ddelrio1986

4
यह वास्तव में सही उत्तर होना चाहिए। दूसरा तरीका भी काम करता है, लेकिन अधिक
दृढ़ है

क्या मतलब है तुम्हारा / अवतारों से? क्या आप कुछ बैकएंड एपीआई एंडपॉइंट की बात कर रहे हैं?
कार्तिकेय मिश्रा

90

Fetch API के साथ फाइल भेजने के लिए एक महत्वपूर्ण नोट

content-typeफ़ेच अनुरोध के लिए हेडर को छोड़ना होगा। फिर ब्राउज़र स्वचालित रूप Content typeसे प्रपत्र सीमा सहित हेडर जोड़ देगा जो दिखता है

Content-Type: multipart/form-data; boundary=—-WebKitFormBoundaryfgtsKTYLsT7PNUVD

प्रपत्र सीमा प्रपत्र डेटा के लिए सीमांकक है


17
यह! बहोत महत्वपूर्ण! मल्टीपार्ट पर लाने के साथ अपनी स्वयं की सामग्री-प्रकार का उपयोग न करें। मुझे नहीं पता था कि मेरा कोड काम क्यों नहीं करता है।
एर्नेस्तस स्टैंकेविसियस


1
यह सोना है! मैं यह समझ नहीं 1 घंटा बर्बाद कर दिया। इस टिप को शेयर करने के लिए धन्यवाद
अश्विन प्रभु

1
डाउनवोट क्योंकि भले ही यह उपयोगी जानकारी है, लेकिन यह ओपी के सवाल का जवाब देने का प्रयास नहीं करता है।
टॉरिटाइट

3
यह बहुत महत्वपूर्ण जानकारी है जो MDN Fetch डॉक्स में कैप्चर नहीं की जाती है ।
प्लास्टर ग्रोव

36

यदि आप कई फाइलें चाहते हैं, तो आप इसका उपयोग कर सकते हैं

var input = document.querySelector('input[type="file"]')

var data = new FormData()
for (const file of input.files) {
  data.append('files',file,file.name)
}

fetch('/avatars', {
  method: 'POST',
  body: data
})

@ Saly3301 मुझे एक ही समस्या थी, यह इसलिए था क्योंकि मेरा एपीआई फ़ंक्शन फॉर्मटाटा को JSON में बदलने की कोशिश कर रहा था। (मैंने केवल बंद मौके पर टिप्पणी की कि यह किसी की मदद करता है)
एमपी ०३५

19

एक एकल फाइल सबमिट करने के लिए, आप बस का उपयोग कर सकते Fileवस्तु से inputकी .filesसरणी सीधे के मूल्य के रूप में body:अपने में fetch()प्रारंभकर्ता:

const myInput = document.getElementById('my-input');

// Later, perhaps in a form 'submit' handler or the input's 'change' handler:
fetch('https://example.com/some_endpoint', {
  method: 'POST',
  body: myInput.files[0],
});

यह काम करता है क्योंकि Fileइनहेरिट करता है Blob, और Fetch Standard में परिभाषित Blobअनुमत BodyInitप्रकारों में से एक है।


यह सबसे सरल उत्तर है लेकिन body: myInput.files[0]ग्राहक की ओर से मेमोरी में आयोजित बाइट्स की मात्रा का कारण कैसे बनता है?
bantol

2
मुझे उम्मीद है कि इस समाधान के साथ ब्राउज़र फ़ाइल को स्ट्रीम करने के लिए काफी समझदार होगा और इसे मेमोरी, @bantol में पढ़ने की आवश्यकता नहीं है, लेकिन मैं पता लगाने के लिए अपने तरीके से बाहर नहीं गया हूं (या तो अनुभवजन्य रूप से या में delving करके कल्पना)। यदि आप पुष्टि करना चाहते हैं, तो आप 50 जीबी फ़ाइल या कुछ और अपलोड करने के लिए इस दृष्टिकोण का उपयोग करके (प्रत्येक प्रमुख ब्राउज़र में) कोशिश कर सकते हैं, और देखें कि क्या आपका ब्राउज़र बहुत अधिक मेमोरी का उपयोग करने की कोशिश करता है और मारा जाता है।
मार्क अमेरी

मेरे लिए काम नहीं किया। express-fileuploadअनुरोध स्ट्रीम पार्स करने में विफल। लेकिन FormDataएक आकर्षण की तरह काम करता है।
अटाकॉमियन

1
@attacomsian एक नज़र में, यह मेरे जैसा दिखता है अनुरोधों express-fileuploadको संभालने के लिए एक सर्वराइड लाइब्रेरी है multipart/form-data, जिसमें फ़ाइलें हैं, इसलिए, यह इस दृष्टिकोण के साथ संगत नहीं है (जो सीधे अनुरोध निकाय के रूप में फ़ाइल भेजता है)।
मार्क अमेरी

6

यहाँ स्वीकृत उत्तर थोड़ा दिनांकित है। अप्रैल 2020 तक, एमडीएन वेबसाइट पर देखा जाने वाला एक अनुशंसित दृष्टिकोण उपयोग करने का सुझाव देता है FormDataऔर सामग्री प्रकार सेट करने के लिए भी नहीं कहता है। https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API/Using_Fetch

मैं सुविधा के लिए कोड स्निपेट उद्धृत कर रहा हूं:

const formData = new FormData();
const fileField = document.querySelector('input[type="file"]');

formData.append('username', 'abc123');
formData.append('avatar', fileField.files[0]);

fetch('https://example.com/profile/avatar', {
  method: 'PUT',
  body: formData
})
.then((response) => response.json())
.then((result) => {
  console.log('Success:', result);
})
.catch((error) => {
  console.error('Error:', error);
});

1
उपयोग FormDataकेवल तभी काम करेगा जब सर्वर फॉर्म डेटा की उम्मीद कर रहा है। यदि सर्वर को एक कच्ची फ़ाइल चाहिए, क्योंकि POST के मुख्य भाग में स्वीकृत उत्तर सही है।
क्लाइड

2

कई फ़ाइल इनपुट तत्वों के लिए एलेक्स मोंटोया के दृष्टिकोण से कूदना

const inputFiles = document.querySelectorAll('input[type="file"]');
const formData = new FormData();

for (const file of inputFiles) {
    formData.append(file.name, file.files[0]);
}

fetch(url, {
    method: 'POST',
    body: formData })

1

मेरे लिए समस्या यह थी कि मैं फॉर्म डेटा को पॉप्युलेट करने के लिए response.blob () का उपयोग कर रहा था। जाहिरा तौर पर आप ऐसा नहीं कर सकते कम से कम प्रतिक्रिया देशी के साथ तो मैंने उपयोग करना समाप्त कर दिया

data.append('fileData', {
  uri : pickerResponse.uri,
  type: pickerResponse.type,
  name: pickerResponse.fileName
 });

लगता है कि प्रारूप उस प्रारूप को पहचानता है और उस फ़ाइल को भेजता है जहां uri इंगित कर रहा है।


0

यहाँ मेरा कोड है:

एचटीएमएल:

const upload = (file) => {
    console.log(file);

    

    fetch('http://localhost:8080/files/uploadFile', { 
    method: 'POST',
    // headers: {
    //   //"Content-Disposition": "attachment; name='file'; filename='xml2.txt'",
    //   "Content-Type": "multipart/form-data; boundary=BbC04y " //"multipart/mixed;boundary=gc0p4Jq0M2Yt08jU534c0p" //  ή // multipart/form-data 
    // },
    body: file // This is your file object
  }).then(
    response => response.json() // if the response is a JSON object
  ).then(
    success => console.log(success) // Handle the success response object
  ).catch(
    error => console.log(error) // Handle the error response object
  );

  //cvForm.submit();
};

const onSelectFile = () => upload(uploadCvInput.files[0]);

uploadCvInput.addEventListener('change', onSelectFile, false);
<form id="cv_form" style="display: none;"
										enctype="multipart/form-data">
										<input id="uploadCV" type="file" name="file"/>
										<button type="submit" id="upload_btn">upload</button>
</form>
<ul class="dropdown-menu">
<li class="nav-item"><a class="nav-link" href="#" id="upload">UPLOAD CV</a></li>
<li class="nav-item"><a class="nav-link" href="#" id="download">DOWNLOAD CV</a></li>
</ul>


1
समीक्षा से: हाय, कृपया स्रोत कोड के साथ जवाब न दें। आपका समाधान कैसे काम करता है, इसके बारे में एक अच्छा विवरण प्रदान करने का प्रयास करें। देखें: मैं एक अच्छा जवाब कैसे लिखूं? । धन्यवाद
sɐunıɔ ןɐ qɐp
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.