2017-05-14 1 views
0

이동 버전 : 1.6.3 맥 OS읽기 다중 요청 결과

나는 서버에 APK 파일 (대부분의 경우 몇 MB)를 업로드 할 수있는 API를 작성하려합니다.

func syncApk(apkFile *os.File) { 
    defer apkFile.Close() 
    var buffer bytes.Buffer 
    writer := multipart.NewWriter(&buffer) 
    defer writer.Close() 
    part, err := writer.CreateFormFile("apk", filepath.Base(apkFile.Name())) 
    if err != nil { 
     fmt.Fprintf(os.Stderr, "Error creating form file: %v\n", err) 
     return 
    } 

    size, err := io.Copy(part, apkFile) 
    if err != nil { 
     fmt.Fprintf(os.Stderr, "Error copying apk file data: %v\n", err) 
     return 
    } 
    fmt.Fprintf(os.Stdout, "Copied %v bytes for uploading...\n", size) 

    response, err := http.Post("http://localhost:8080/upload", writer.FormDataContentType(), &buffer) 

    if err != nil { 
     fmt.Fprintf(os.Stderr, "Error making POST request to sync apk: %v\n", err) 
     return 
    } 

    fmt.Fprintf(os.Stdout, "Successfully uploaded apk file: %v\n", response.StatusCode) 
} 

서버 코드 : 나는 로컬 호스트에 서버를 실행 한 후

func main() { 
    server := http.Server{ 
     Addr: ":8080", 
    } 
    http.HandleFunc("/upload", doApkUpload) 
    server.ListenAndServe() 
} 

func doApkUpload(w http.ResponseWriter, r *http.Request) { 
    file, _, err := r.FormFile("apk") 
    if err != nil { 
     fmt.Fprintf(os.Stderr, "Error retrieving apk file: %v\n", err) 
     return 
    } 

    data, err := ioutil.ReadAll(file) 
    if err != nil { 
     fmt.Fprintf(os.Stderr, "Error reading apk file content: %v", err) 
     return 
    } 

    fmt.Fprintf(os.Stdout, string(data)) 
} 

내가 클라이언트 측 코드를 실행, 내가 얻을 :

Copied 1448401 bytes for uploading... 
Successfully uploaded apk file: 200 

그것은처럼 보이는 다음은 클라이언트 측 코드는 multipart 파일이 올바르게 기록됩니다. 그러나 서버 측에서이 오류가 표시됩니다.

Error retrieving apk file: unexpected EOF 

어디에서 문제가 발생합니까? 감사!

+1

클라이언트 쪽 코드에'http.Post' 다음에'defer response.Body.Close()'를 추가해야한다고 생각합니다. – putu

+0

@putu 네가 맞다. 나는 라인을 추가했지만 문제를 해결하지는 못한다. – darklord

답변

1

오류는 요청 본문이 끝난 후 독자가 더 많은 데이터를 예상했음을 나타냅니다. 그 누락 된 데이터는 multipart Close 메서드에 의해 쓰여진 후행 경계 끝선입니다.

모든 부품을 작성한 후 양식을 게시하기 전에 Close 메소드를 호출하십시오.

func syncApk(apkFile *os.File) { 
    defer apkFile.Close() 
    var buffer bytes.Buffer 
    writer := multipart.NewWriter(&buffer) 
    part, err := writer.CreateFormFile("apk", filepath.Base(apkFile.Name())) 
    if err != nil { 
     fmt.Fprintf(os.Stderr, "Error creating form file: %v\n", err) 
     return 
    } 

    size, err := io.Copy(part, apkFile) 
    if err != nil { 
     fmt.Fprintf(os.Stderr, "Error copying apk file data: %v\n", err) 
     return 
    } 
    fmt.Fprintf(os.Stdout, "Copied %v bytes for uploading...\n", size) 
    writer.Close() 
    response, err := http.Post("http://localhost:8080/upload", writer.FormDataContentType(), &buffer) 

    if err != nil { 
     fmt.Fprintf(os.Stderr, "Error making POST request to sync apk: %v\n", err) 
     return 
    } 
    defer response.Body.Clse() 

    fmt.Fprintf(os.Stdout, "Successfully uploaded apk file: %v\n", response.StatusCode) 
}