लाने के लिए प्रगति संकेतक अपलोड करें?


101

मैं प्रलेखन का उपयोग करने के लिए संघर्ष कर रहा हूं या एक अपलोड प्रगति संकेतक को लाने के उदाहरणों का उपयोग कर रहा हूं ।

यह एकमात्र संदर्भ है जो मैंने अब तक पाया है , जो बताता है:

प्रगति की घटनाएँ एक उच्च स्तरीय विशेषता है जो अब तक नहीं आएगी। आप Content-Lengthहेडर को देखकर और प्राप्त बाइट्स की निगरानी के लिए एक पास-थ्रू स्ट्रीम का उपयोग करके अपना खुद का बना सकते हैं ।

इसका मतलब है कि आप स्पष्ट रूप से एक Content-Lengthअलग तरीके से प्रतिक्रियाओं को संभाल सकते हैं । और हां, भले ही Content-Lengthयह एक झूठ हो सकता है। धाराओं के साथ आप इन झूठों को संभाल सकते हैं जो आप चाहते हैं।

मैं "बाइट्स की निगरानी के लिए एक पास-थ्रू स्ट्रीम" कैसे लिखूंगा? यदि यह किसी प्रकार का अंतर करता है, तो मैं ब्राउज़र से क्लाउडिनरी में पावर इमेज अपलोड करने के लिए ऐसा करने की कोशिश कर रहा हूं ।

नोट : मुझे क्लाउडिनरी जेएस लाइब्रेरी में कोई दिलचस्पी नहीं है , क्योंकि यह jQuery पर निर्भर करता है और मेरा ऐप नहीं करता है। मैं केवल देशी जावास्क्रिप्ट और Github के पॉलीफ़िल के साथ ऐसा करने के लिए आवश्यक स्ट्रीम प्रसंस्करण में दिलचस्पी रखता हूं ।fetch


https://fetch.spec.whatwg.org/#fetch-api


4
@ मैगिक्स एब्स को एबॉर्टिंग करते हुए देखें : अगली पीढ़ी # 447
गेस्ट 271314

जवाबों:


44

वेब प्लेटफ़ॉर्म में स्ट्रीम शुरू हो रही हैं ( https://jakearchibald.com/2016/streams-ftw/ ) लेकिन अभी भी शुरुआती दिन हैं।

जल्द ही आप अनुरोध के निकाय के रूप में एक स्ट्रीम प्रदान कर पाएंगे, लेकिन खुला सवाल यह है कि क्या उस स्ट्रीम की खपत अपलोड बाइट्स से संबंधित है।

विशेष रूप से पुनर्निर्देशन के परिणामस्वरूप डेटा को नए स्थान पर ले जाया जा सकता है, लेकिन धाराएं "पुनः आरंभ" नहीं कर सकती हैं। हम शरीर को कॉलबैक में बदलकर इसे ठीक कर सकते हैं, जिसे कई बार कहा जा सकता है, लेकिन हमें यह सुनिश्चित करने की आवश्यकता है कि पुनर्निर्देशन की संख्या को उजागर करना सुरक्षा रिसाव नहीं है, क्योंकि यह प्लेटफ़ॉर्म जेएस पर पहली बार हो सकता है। उस का पता लगाएं।

कुछ सवाल कर रहे हैं कि क्या यह भी स्ट्रीम खपत को बाइट्स अपलोड करने के लिए समझ में आता है।

लंबी कहानी छोटी: यह अभी तक संभव नहीं है, लेकिन भविष्य में इसे या तो धाराओं द्वारा नियंत्रित किया जाएगा, या किसी प्रकार की उच्च-स्तरीय कॉलिंग में पारित किया जाएगा fetch()


7
बहुत बुरा। अभी के लिए इसे स्वीकार करना, लेकिन जब यह एक वास्तविकता बन जाती है, तो मुझे उम्मीद है कि कोई और व्यक्ति एक अद्यतन समाधान पोस्ट करेगा! :)
नीपर 19

1
अद्यतन - धाराओं का उपयोग करके भ्रूण एपीआई के साथ प्रगति दिखाना - twitter.com/umaar/status/917789464658890753/photo/1
इटान पीयर

2
@ EitanPeer अच्छा लगा। क्या अपलोड करने के लिए एक समान काम करेगा, जैसे POST?
माइकल

4
@ EitanPeer लेकिन, सवाल अपलोड में प्रगति के बारे में है, डाउनलोड में नहीं
जॉन बल्विन एरियस

1
यह अब 2020 है, क्यों अभी भी ऐसा करने का कोई तरीका नहीं है :(
MHA15

24

मेरा समाधान अक्षतंतु का उपयोग करना है , जो इस काफ़ी अच्छी तरह से समर्थन करता है:

      axios.request( {
        method: "post", 
        url: "/aaa", 
        data: myData, 
        onUploadProgress: (p) => {
          console.log(p); 
          //this.setState({
            //fileprogress: p.loaded / p.total
          //})
        }


      }).then (data => {
        //this.setState({
          //fileprogress: 1.0,
        //})
      })

मेरे पास गितुब पर प्रतिक्रिया में इसका उपयोग करने के लिए उदाहरण है


2
यही मेरा समाधान भी था। एक्सियोस मोल्ड को वास्तव में अच्छी तरह से फिट करने के लिए लगता है।
जेसन राइस

1
का axiosउपयोग करता है fetchया XMLHttpRequestअंडर-हुड?
दाई

3
XMLHttpRequest। यदि आप इसका उपयोग देशी प्रतिक्रिया के लिए कर रहे हैं, तो सावधान रहें कि XMLHttpRequest ऐसा प्रतीत होता है कि भ्रूण की तुलना में बड़े जोंस प्रतिक्रियाओं को धीमा करने के लिए बहुत धीमा है (लगभग 10 गुना धीमा है, और यह पूरे ui धागे को जमा देता है)।
क्रिस्टियानो कोएल्हो

22
सवाल का जवाब नहीं! यदि प्रश्न "आप y में x कैसे करते हैं?" "इसके बजाय एक्स इन ज़ेड करो" स्वीकार्य उत्तर नहीं है।
डेरेक हेंडरसन

4
यह सवाल का जवाब नहीं देता है, खासकर क्योंकि हुड के तहत axiosउपयोग नहीं करता fetchहै, और ऐसा कोई समर्थन नहीं है। मैं सचमुच यह अब उनके लिए संलेखन कर रहा हूँ ।
sgammon

7

मुझे नहीं लगता कि यह संभव है। मसौदा बताता है:

यह वर्तमान में [कमी है एक्सएचआर की तुलना में ] जब यह अनुरोध प्रगति की बात आती है


(पुराना उत्तर): Fetch API अध्याय
में पहला उदाहरण कुछ अंतर्दृष्टि देता है कि कैसे:

यदि आप शरीर का डेटा उत्तरोत्तर प्राप्त करना चाहते हैं:

function consume(reader) {
  var total = 0
  return new Promise((resolve, reject) => {
    function pump() {
      reader.read().then(({done, value}) => {
        if (done) {
          resolve()
          return
        }
        total += value.byteLength
        log(`received ${value.byteLength} bytes (${total} bytes in total)`)
        pump()
      }).catch(reject)
    }
    pump()
  })
}

fetch("/music/pk/altes-kamuffel.flac")
  .then(res => consume(res.body.getReader()))
  .then(() => log("consumed the entire body without keeping the whole thing in memory!"))
  .catch(e => log("something went wrong: " + e))

Promiseकंस्ट्रक्टर एंटीपैटर्न के उनके उपयोग के अलावा , आप देख सकते हैं कि response.bodyएक स्ट्रीम है जिसमें से आप एक रीडर का उपयोग करके बाइट पढ़ सकते हैं, और आप उनमें से हर एक के लिए किसी ईवेंट को आग लगा सकते हैं या जो आपको पसंद है (जैसे कि प्रगति को लॉग इन करें)।

हालाँकि, स्ट्रीम कल्पना काफी हद तक समाप्त नहीं होती है, और मुझे नहीं पता कि यह पहले से ही किसी भी कार्यान्वयन में काम करती है।


11
यदि मैं उस उदाहरण को सही ढंग से पढ़ता हूं, हालांकि, यह एक फ़ाइल को डाउनलोड करने के लिए होगा fetch। मैं एक फ़ाइल अपलोड करने के लिए प्रगति संकेतक में रुचि रखता हूं ।
23

उफ़, वह उद्धरण बाइट्स प्राप्त करने के बारे में बात करता है , जिसने मुझे भ्रमित किया।
बेर्गी

@ बर्गी नोट, Promiseकंस्ट्रक्टर आवश्यक नहीं है। Response.body.getReader()एक रिटर्न Promiseबड़े आकार के जोंस को डाउनलोड करते समय अनक्रेन्डेड रेंज को हल करने का तरीका
271314

3
@ Guest271314 हाँ, मैंने इसे पहले ही उद्धरण के स्रोत पर तय कर दिया है । और नहीं, getReaderएक वादा वापस नहीं करता है। कोई भी विचार यह नहीं है कि आपके द्वारा लिंक किए गए पोस्ट के साथ क्या करना है।
बरगी

@Bergi हाँ, आप सही हैं .getReader()की .read()विधि एक रिटर्न Promise। यही वह बताने की कोशिश कर रहा था। लिंक को इस आधार पर जोड़ना है कि यदि प्रगति को डाउनलोड करने के लिए जाँच की जा सकती है, तो अपलोड के लिए प्रगति की जाँच की जा सकती है। एक साथ एक पैटर्न रखो जो अपेक्षित परिणाम देता है, एक प्रशंसनीय डिग्री के लिए; यह fetch()अपलोड के लिए प्रगति है । Jsfiddle पर echoएक ऑब्जेक्ट Blobया Fileऑब्जेक्ट का रास्ता नहीं मिला है , शायद कुछ सरल याद आ रहा है। पर परीक्षण localhostअपलोड फ़ाइल बहुत तेजी से, नेटवर्क शर्तों नकल उतार के बिना; हालाँकि अभी याद आया Network throttling
.१३१४

6

अद्यतन: जैसा कि स्वीकार किया गया उत्तर कहता है कि यह अब असंभव है। लेकिन नीचे दिए गए कोड ने कुछ समय के लिए हमारी समस्या को संभाल लिया। मुझे यह जोड़ना चाहिए कि कम से कम हमें एक पुस्तकालय का उपयोग करने के लिए स्विच करना था जो XMLHttpRequest पर आधारित है।

const response = await fetch(url);
const total = Number(response.headers.get('content-length'));

const reader = response.body.getReader();
let bytesReceived = 0;
while (true) {
    const result = await reader.read();
    if (result.done) {
        console.log('Fetch complete');
        break;
    }
    bytesReceived += result.value.length;
    console.log('Received', bytesReceived, 'bytes of data so far');
}

इस लिंक के लिए धन्यवाद: https://jakearchibald.com/2016/streams-ftw/


2
अच्छा लगा, लेकिन क्या यह अपलोड पर भी लागू होता है?
कर्नेल

@ कर्नेल मैंने यह जानने की कोशिश की लेकिन मैं ऐसा करने में सक्षम नहीं था। और मुझे अपलोड करने के लिए ऐसा करने का तरीका खोजना पसंद है।
१२:५२ पर होसेनम्पैक्टर १६

वही, लेकिन अब तक मैं एक कामकाजी अपलोड उदाहरण खोजने / बनाने में बहुत भाग्यशाली नहीं था।
कर्नल

1
content-length! == शरीर की लंबाई। जब http कम्प्रेशन का उपयोग किया जाता है (बड़े डाउनलोड के लिए सामान्य), सामग्री-लंबाई http संपीड़न के बाद आकार है, जबकि लंबाई फ़ाइल को निकाले जाने के बाद का आकार है।
फेरीबिग

@Ferrybig मुझे आपकी बात नहीं मिली। क्या मैंने समानता का उपयोग कहीं?
होसेनम्पैक्टर76

4

चूंकि कोई भी उत्तर समस्या का समाधान नहीं करता है।

बस कार्यान्वयन के लिए, आप ज्ञात आकार के कुछ छोटे प्रारंभिक भाग के साथ अपलोड गति का पता लगा सकते हैं और अपलोड समय की गणना सामग्री-लंबाई / अपलोड-गति के साथ की जा सकती है। आप इस समय का अनुमान के रूप में उपयोग कर सकते हैं।


3
बहुत चालाक, अच्छी चाल का उपयोग करते हुए जब हम एक रीयलटाइम समाधान की प्रतीक्षा करते हैं :)
मगिक्स


2

एक संभावित समाधान new Request()निर्माणकर्ता का उपयोग करना तब Request.bodyUsed Booleanविशेषता की जांच करना होगा

bodyUsedविशेषता के गेटर अगर सच लौटना चाहिए disturbedअन्यथा, और झूठे।

यह निर्धारित करने के लिए कि क्या धारा है distributed

Bodyमिक्सिन को लागू करने वाली एक वस्तु को कहा जाता है कि disturbedयदि bodyवह अशक्त है और उसकी streamहै disturbed

जंजीर के fetch() Promiseभीतर से लौटें जब एक के .then()पुनरावर्ती .read()कॉल करने के लिए बराबर है ।ReadableStreamRequest.bodyUsedtrue

ध्यान दें, दृष्टिकोण के बाइट्स को नहीं पढ़ता है क्योंकि बाइट्स Request.bodyसमापन बिंदु पर प्रवाहित होते हैं। साथ ही, ब्राउज़र में किसी भी प्रतिक्रिया के पूर्ण होने से पहले अपलोड अच्छी तरह से पूरा हो सकता है।

const [input, progress, label] = [
  document.querySelector("input")
  , document.querySelector("progress")
  , document.querySelector("label")
];

const url = "/path/to/server/";

input.onmousedown = () => {
  label.innerHTML = "";
  progress.value = "0"
};

input.onchange = (event) => {

  const file = event.target.files[0];
  const filename = file.name;
  progress.max = file.size;

  const request = new Request(url, {
    method: "POST",
    body: file,
    cache: "no-store"
  });

  const upload = settings => fetch(settings);

  const uploadProgress = new ReadableStream({
    start(controller) {
        console.log("starting upload, request.bodyUsed:", request.bodyUsed);
        controller.enqueue(request.bodyUsed);
    },
    pull(controller) {
      if (request.bodyUsed) {
        controller.close();
      }
      controller.enqueue(request.bodyUsed);
      console.log("pull, request.bodyUsed:", request.bodyUsed);
    },
    cancel(reason) {
      console.log(reason);
    }
  });

  const [fileUpload, reader] = [
    upload(request)
    .catch(e => {
      reader.cancel();
      throw e
    })
    , uploadProgress.getReader()
  ];

  const processUploadRequest = ({value, done}) => {
    if (value || done) {
      console.log("upload complete, request.bodyUsed:", request.bodyUsed);
      // set `progress.value` to `progress.max` here 
      // if not awaiting server response
      // progress.value = progress.max;
      return reader.closed.then(() => fileUpload);
    }
    console.log("upload progress:", value);
    progress.value = +progress.value + 1;
    return reader.read().then(result => processUploadRequest(result));
  };

  reader.read().then(({value, done}) => processUploadRequest({value,done}))
  .then(response => response.text())
  .then(text => {
    console.log("response:", text);
    progress.value = progress.max;
    input.value = "";
  })
  .catch(err => console.log("upload error:", err));

}

-3
const req = await fetch('./foo.json');
const total = Number(req.headers.get('content-length'));
let loaded = 0;
for await(const {length} of req.body.getReader()) {
  loaded = += length;
  const progress = ((loaded / total) * 100).toFixed(2); // toFixed(2) means two digits after floating point
  console.log(`${progress}%`); // or yourDiv.textContent = `${progress}%`;
}

मैं पूरे जवाब के लिए बेंजामिन ग्रुएनबाम को एक क्रेडिट देना चाहता हूं। क्योंकि मैंने इसे उनके व्याख्यान से सीखा था।
लियोन गिलाडोव

@LeGGadadov व्याख्यान कहीं भी ऑनलाइन उपलब्ध है? स्रोत का लिंक अच्छा होगा।
मार्क अमेरी

@MarkAmery यहां यह है: youtube.com/watch?v=Ja8GKkxahCo (व्याख्यान हिब्रू में दिया गया था)
लियोन गिलाडोव

11
सवाल अपलोड करने का है, डाउनलोड करने का नहीं।
सरनेह

प्रगति के साथ समस्या यह है कि जब आप अपलोड करना चाहते हैं (डाउनलोड के साथ कोई समस्या नहीं है)
कामिल Kiełczewski

-5

महत्वपूर्ण हिस्सा है ReadableStream « obj_response .body»।

नमूना:

let parse=_/*result*/=>{
  console.log(_)
  //...
  return /*cont?*/_.value?true:false
}

fetch('').
then(_=>( a/*!*/=_.body.getReader(), b/*!*/=z=>a.read().then(parse).then(_=>(_?b:z=>z)()), b() ))

आप इसे एक बड़े पृष्ठ जैसे https://html.spec.whatwg.org/ और https://html.spec.whatwg.org/print.pdf पर चलाने का परीक्षण कर सकते हैं । CtrlSiftJ और कोड को लोड करें।

(क्रोम पर परीक्षण किया गया।)


1
इस उत्तर को माइनस पॉइंट्स मिलते हैं, लेकिन कोई भी यह नहीं बताता कि माइनस पॉइंट क्यों देते हैं - इसलिए मैं +1 देता हूं
कामिल किल्सेवस्की

4
यह मेरे से -1 हो जाता है क्योंकि यह अपलोड करने के लिए प्रासंगिक नहीं है ।
ब्रैड
हमारी साइट का प्रयोग करके, आप स्वीकार करते हैं कि आपने हमारी Cookie Policy और निजता नीति को पढ़ और समझा लिया है।
Licensed under cc by-sa 3.0 with attribution required.