2016-04-27 9 views
2
func SimpleUploader(r *http.Request, w http.ResponseWriter) { 
    // temp folder path 
    chunkDirPath := "./creatives/.uploads/" + userUUID 
    // create folder 
    err = os.MkdirAll(chunkDirPath, 02750) 

    // Get file handle from multipart request 
    var file io.Reader 
    mr, err := r.MultipartReader() 

    var fileName string 
    // Read multipart body until the "file" part 
    for { 
     part, err := mr.NextPart() 
     if err == io.EOF { 
      break 
     } 
     if part.FormName() == "file" { 
      file = part 
      fileName = part.FileName() 
      fmt.Println(fileName) 
      break 
     } 
    } 

    // Create files 
    tempFile := chunkDirPath + "/" + fileName 
    dst, err := os.Create(tempFile) 

    defer dst.Close() 

    buf := make([]byte, 1024*1024) 
    file.Read(buf) 
    // write/save buffer to disk 
    ioutil.WriteFile(tempFile, buf, os.ModeAppend) 
    if http.DetectContentType(buf) != "video/mp4" { 
     response, _ := json.Marshal(&Response{"File upload cancelled"}) 
     settings.WriteResponse(w, http.StatusInternalServerError, response) 
     return 
    } 

    // joinedFile := io.MultiReader(bytes.NewReader(buf), file) 
    _, err = io.Copy(dst, file) 
    if err != nil { 
     settings.LogError(err, methodName, "Error copying file") 
    } 

    response, _ := json.Marshal(&Response{"File uploaded successfully"}) 
    settings.WriteResponse(w, http.StatusInternalServerError, response) 
} 

私はビデオファイルをアップロードしています。 ファイル全体をアップロードする前に、私は、ファイルへの最初の1メガバイトを保存するように、いくつかのチェックをしたい。そして、ファイルを追加する方法(io.Reader)?

buf := make([]byte, 1024*1024) 
file.Read(buf) 
// write/save buffer to disk 
ioutil.WriteFile(tempFile, buf, os.ModeAppend) 

チェックが、私は、ファイルの残りの部分をアップロードしたい渡す場合dst is the same file used to save the 1st 1 mbので、基本的に私がしようとしていますファイルに添付してください:

_, err = io.Copy(dst, file) 

アップロードされたファイルのサイズは正しくありますが、ファイルが壊れています(ビデオを再生できません)。

他に何を試しましたか? :リーダーに参加して新しいファイルに保存します。しかし、このアプローチでは、ファイルサイズが1 MB増加し、破損します。

joinedFile := io.MultiReader(bytes.NewReader(buf), file) 
_, err = io.Copy(newDst, joinedFile) 

助けてください。あなたは基本的に問題があること

os.Createを実行してファイルを2回開いて、ioutil.WriteFile

まし

+1

これをテストするファイルのサイズは?あなたがバッファに読み込まれたバイト数をチェックしていないか、 'file.Read(buf)'を実行したときにエラーが返されたようです。 –

+0

私は200 MBファイルでテストしています。質問を短縮するためのすべてのエラーチェックを削除しました。そのステップにエラーはありません。 – Monodeep

+0

私は2番目のDeanのコメントになります。エラーがないからといって、バッファーがリーダーからのデータで満たされているわけではありません。ストリーム上の1つの読み込みがこの大きなバッファを満たすことは決して想像できません。第2に、ioutil関数はうまくいきますが、ファイルのio.Writerインターフェイスを使用して簡単に書き込むことができ、必要に応じてSeek()を使用して書き込み位置を調整できます。 –

答えて

1

はos.Createの戻り値(DST)は、そのファイルの先頭へのポインタのようなものであるということです。 WriteFileは、dstが指す場所には移動しません。

基本的にはWriteFileを実行してから、最初のバイトセットの先頭にio.Copyを追加します。

WriteFileを最初に(作成フラグを使用して)、次にos.OpenFile(os.Createではなく)に、同じファイルにAppendフラグを付けて残りのバイトを末尾に追加します。

また、クライアントがあなたにファイル名を与えることは非常に危険です。たとえば、あなたが決めるものをシェルのinitに上書きするような、../../.bashrc(例えば)です。アップロードする。

ファイル名を自分で計算した方が安全です。ユーザーが選択したファイル名を覚えておく必要がある場合は、そのファイルをデータベースに格納します。後でロードするmetadata.jsonタイプのファイルにも格納します。

+0

私がこれを行ったので、 ioutil.WriteFile(TEMPFILE、BUF、0644) 'そして' DST、ERR:= os.OpenFile(一時ファイル、os.O_RDWR | os.O_APPEND、0666) \t延期dst.Close() \t _、ERR = IO。コピー(dst、file) 'まだファイルサイズは1MB増えて壊れています。 – Monodeep

関連する問題