मेरे पास एक्सप्रेस के साथ नोड.जेएस में एक पोस्ट राउटर का कार्यान्वयन है। पोस्ट का मुख्य भाग फाइलों की एक सूची है, और विचार यह है कि इन फ़ाइलों को ज़िप किया जाना चाहिए और परिणामी ज़िप फ़ाइल का एक लिंक वापस किया जाना चाहिए। मैं ज़िप की गई फ़ाइलों की संख्या के साथ-साथ ज़िप के फ़ाइल नाम के पूरा होने पर प्रगति को संग्रहीत करने के लिए 'एक्सप्रेस-सत्र' का उपयोग करने का प्रयास कर रहा हूं। ज़िप की गई फ़ाइलों की संख्या को अपडेट करना (req.session.current) ठीक काम करता है, लेकिन किसी कारण से मैं फ़ाइल नाम (req.session.zipFile) को सत्र में सेट नहीं कर सकता जब फ़ाइलस्ट्रीम बंद हो जाता है। मुझे संदेह है कि req ऑब्जेक्ट अब fileStream.on('close') तक पहुंचने तक मान्य नहीं है, लेकिन मुझे यकीन नहीं है कि इसे कैसे संभालना है। मैं अनुरोध के बिना सत्र डेटा तक नहीं पहुंच सकता। यह संपूर्ण राउटर कार्यान्वयन है:

const express = require('express');
const router = express.Router();
const fs = require('fs');
const ZIP_FILES_PATH = require('../constants');


router.post('/', function(req, res, next){
    const json = JSON.parse(req.body.data);
    const path = json["base"];
    if (!path || path.length === 0){
        res.render("error", {msg: "JSON missing 'base'"})
        return;
    }
    const files = json["files"];
    if (!files || files.length === 0){
        res.statusCode = 400;
        res.send("JSON missing 'files'");
        return;
    }
    if (!fs.existsSync(path)) {
        res.statusCode = 400;
        res.send("Directory '" + path + "' does not exist");
        return;
    }
    try{
        var sessData = req.session;
            sessData.total = files.length ;
            sessData.current = 0;
            sessData.zipFile = '';
            zipFiles(path, files, req, res);
    }catch(error){
        res.statusCode = 500;
        res.send("The files could not be zipped");
        return;
    }
    res.render("zipping")
});
module.exports = router;

const zipFiles = (path, files, req, res) => {
    const zipFile = require('crypto').createHash('md5').update(path).digest("hex") + "_" + new Date().getTime() + ".zip";
    const archiver = require('archiver');
    const fileStream = fs.createWriteStream(ZIP_FILES_PATH + zipFile);
    const archive = archiver('zip', {
    gzip: true,
    zlib: { level: 9 }
    });

    archive.on('error', function(err) {
        throw err;
    });
    fileStream.on('close', function() {
        req.session.zipFile = "/download?file=" + zipFile; //Doesn't stick!
    });
    archive.pipe(fileStream);
    files.map(file => zipSingleFile(path, file, req, archive));
    archive.finalize();

}
const zipSingleFile = (path, file, req, archive)  => {
    fs.existsSync(path + "/" + file) ? archive.file(path + "/" + file, { name: file }) : null;
    req.session.current = req.session.current + 1;
}
0
Jonas Rosenqvist 13 नवम्बर 2018, 11:15

1 उत्तर

सबसे बढ़िया उत्तर

zipFiles() अतुल्यकालिक है। इसका मतलब है कि यह ब्लॉक नहीं होता है और कुछ समय बाद खत्म हो जाता है। तो, आपके अनुरोध हैंडलर के प्रवाह में, आप कॉल करते हैं

res.render("zipping")

zipFiles() खत्म होने से पहले। और, res.render() प्रतिक्रिया भेजेगा और आउटपुट स्ट्रीम को बंद कर देगा।

यदि आप res.render() को कॉल करने के लिए प्रतीक्षा करना चाहते हैं जब तक कि आप zipFiles() कॉल के साथ समाप्त नहीं हो जाते, तो आपको या तो इसे zipFiles() के भीतर से कॉल करना होगा जब यह सब हो चुका हो या आपको एक जोड़ने की आवश्यकता हो zipFiles() पर कॉलबैक करें ताकि जब यह हो जाए तो यह वापस संचार कर सके।

साथ ही, क्या कोई कारण है कि आप res.render() को कॉल करने से पहले req.session.zipFile = "/download?file=" + zipFile; सेट नहीं कर सकते?


साथ ही, इस पर निर्भर करते हुए कि आपने अपना सत्र कैसे कॉन्फ़िगर किया है (जिसके लिए आप हमें कोई कोड नहीं दिखाते हैं), बस यह कर रहे हैं:

req.session.zipFile  = "/download?file=" + zipFile;

वास्तव में उस मान को सत्र में सहेजने के लिए पर्याप्त नहीं हो सकता है। आपको सत्र में .save() को भी कॉल करना पड़ सकता है।


और, आप सेटिंग कर रहे हैं:

req.session.zipFile

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

1
jfriend00 13 नवम्बर 2018, 08:22