2014-10-15 8 views
7

मैं अपलोड करने वाली फ़ाइलों को अनुमति देना चाहता हूं। अनुरोधों को संभालने के लिए जाओ सर्वर-साइड का उपयोग किया जा रहा है। जब भी वे अपलोड करने का प्रयास कर रहे हैं, तो वे "बहुत बड़ी फ़ाइल" प्रतिक्रिया भेजना चाहेंगे, जो बहुत बड़ी है। मैं ऐसा करना चाहता हूं, से पहले पूरी फ़ाइल अपलोड की गई है (बैंडविड्थ)।गोलांग फ़ाइल अपलोड: फ़ाइल बहुत बड़ी है तो बंद कनेक्शन

मैं निम्नलिखित स्निपेट का उपयोग कर रहा हूं, लेकिन क्लाइंट अपलोड होने के बाद ही यह प्रतिक्रिया भेज रहा है। यह 5 केबी फाइल बचाता है।

const MaxFileSize = 5 * 1024 
// This feels like a bad hack... 
if r.ContentLength > MaxFileSize { 
    if flusher, ok := w.(http.Flusher); ok { 
     response := []byte("Request too large") 
     w.Header().Set("Connection", "close") 
     w.Header().Set("Content-Length", fmt.Sprintf("%d", len(response))) 
     w.WriteHeader(http.StatusExpectationFailed) 
     w.Write(response) 
     flusher.Flush() 
    } 
    conn, _, _ := w.(http.Hijacker).Hijack() 
    conn.Close() 
    return 
} 

r.Body = http.MaxBytesReader(w, r.Body, MaxFileSize) 

err := r.ParseMultipartForm(1024) 
if err != nil { 
    w.Write([]byte("File too large")); 
    return 
} 

file, header, err := r.FormFile("file") 
if err != nil { 
    panic(err) 
} 

dst, err := os.Create("upload/" + header.Filename) 
defer dst.Close() 
if err != nil { 
    panic(err) 
} 

written, err := io.Copy(dst, io.LimitReader(file, MaxFileSize)) 
if err != nil { 
    panic(err) 
} 

if written == MaxFileSize { 
    w.Write([]byte("File too large")) 
    return 
} 
w.Write([]byte("Success...")) 
+2

ट्रिकी। हो सकता है कि आप 'MaxFileSize + 1' बाइट्स को पढ़ने के लिए io.CopyN का उपयोग कर सकें। अगर 'गलती! = ईओएफ', सीमा पार हो गई थी या कुछ और समस्या थी। मुझे यकीन नहीं है कि ब्राउज़र में उपयोगकर्ता क्या व्यवहार करेगा यदि आप ऐसा करते हैं, हालांकि - इसे आज़माएं और देखें। साथ ही, मैं समझता हूं कि यह परीक्षण कोड है, लेकिन 'पैनिक से त्रुटि रिटर्न में स्विचिंग आपके उत्पादन कोड के लिए एक अच्छा विचार है। – twotwotwo

+1

सुझाव के लिए धन्यवाद। 'CopyN' के साथ 'कॉपी' को प्रतिस्थापित करना और 'MaxFileSize + 1' बाइट्स पढ़ने से मदद नहीं मिली (ब्राउज़र अंत में)। पैनिक्स के रूप में, मेरे पास आमतौर पर एक विशेष 'रिकवर हैंडलर' होता है, जो पैनिक्स से ठीक हो जाता है और परिणामस्वरूप एक अच्छी त्रुटि 400 पेज होती है। हालांकि ध्यान देने के लिए धन्यवाद। –

उत्तर

13

अधिकतर ग्राहक अनुरोध लिखने तक प्रतिक्रिया नहीं पढ़ते हैं। सर्वर से किसी त्रुटि के जवाब में इन क्लाइंटों को लिखना बंद नहीं होगा।

नेट/http सर्वर 100 continue status का समर्थन करता है।

func handler(w http.ResponseWriter, r *http.Request) { 
    if r.ContentLength > MaxFileSize { 
    http.Error(w, "request too large", http.StatusExpectationFailed) 
    return 
    } 
    r.Body = http.MaxBytesReader(w, r.Body, MaxFileSize) 
    err := r.ParseMultipartForm(1024) 

    // ... continue as before 

ग्राहक "की अपेक्षा: 100-जारी रखने के लिए" भेजा है: इस सुविधा का उपयोग करने के लिए, सर्वर अनुप्रयोग अनुरोध शरीर को पढ़ने से पहले एक त्रुटि के साथ जवाब देना चाहिए हैडर, तो ग्राहक 100 के लिए इंतजार करना चाहिए जारी रखने के लिए स्थिति अनुरोध निकाय लिखने से पहले। सर्वर अनुप्रयोग अनुरोध निकाय को पढ़ता है जब नेट/http सर्वर स्वचालित रूप से 100 जारी स्थिति भेजता है। सर्वर अनुरोध को पढ़ने से पहले त्रुटि के साथ जवाब देकर अनुरोध निकाय को लिखने से रोक सकता है।

नेट/http क्लाइंट does not support the 100 continue status

यदि क्लाइंट ने अपेक्षित हेडर नहीं भेजा है और सर्वर अनुरोध पूर्ण अनुरोध निकाय के बिना अनुरोध हैंडलर से लौटाता है, तो नेट/http सर्वर 256 < < अनुरोध निकाय के 10 बाइट्स को पढ़ता है और हटा देता है। अगर पूरा अनुरोध निकाय नहीं पढ़ा गया तो सर्वर कनेक्शन बंद कर देगा।

+1

क्या ग्राहक को 'अपेक्षा: 100-जारी रखने वाला' हेडर भेजने के लिए "पूछने" का कोई तरीका है? जिस तरह से मैंने इसे हल किया (प्रश्न में संपादित करें), थोड़े हैकी लगता है। हालांकि उत्तर के लिए धन्यवाद! –

+0

आपने इसे कैसे हल किया? क्या आप एक समाधान साझा कर सकते हैं? AFAICT http.ServeHTTP (आर, डब्ल्यू) 100-जारी रखने के साथ स्वचालित रूप से प्रतिक्रिया देता है और सर्वर को ऐसा करने से रोकता है। – jrwren

+0

सर्वर स्वचालित रूप से [अनुरोध निकाय के पहले पढ़ने] पर जारी 100 के साथ प्रतिक्रिया देता है (https://github.com/golang/go/blob/023556c07166be15a914d1f828d8c7b20a59a804/src/net/http/server.go#L790-L804)। StatusExpectationFailed के साथ प्रतिक्रिया देने से पहले अनुरोध निकाय को न पढ़ें। –

संबंधित मुद्दे