У меня есть файловый сервер go, который может принимать запросы файлов размером до 10 ГБ. Чтобы поддерживать низкое использование памяти, я считал данные многочастной формы в файл tmp. Я знаю, что за кулисами FormFile делает то же самое, но мне все еще нужно перенести его в обычный файл для некоторой обработки после загрузки.
f, header, err := r.FormFile("file")
if err != nil {
return nil, fmt.Errorf("could not get file from request %w", err)
}
tmpFile, err := ioutil.TempFile("", "oriio-")
if err != nil {
return nil, err
}
if _, err := io.Copy(tmpFile, f); err != nil {
return nil, fmt.Errorf("could not copy request body to file %w", err)
}
После этого мне нужно получить первые 261 байт файла, чтобы определить его MIME-тип.
head := make([]byte, 261)
if _, err := tmpFile.Read(head); err != nil {
return nil, err
}
Проблема, с которой я сталкиваюсь, заключается в том, что, если я пытаюсь читать напрямую из tmpFile, массив байтов возвращает 261 0, когда я печатаю fmt.Prinf("%x", head)
или недействительные данные. Чтобы убедиться, что данные действительны, я сохранял их в обычный файл, открывая его в моей системе, и файл (в данном случае файл изображения) был в идеальном состоянии. Так что это не проблема поврежденного файла. Чтобы обойти проблему, я теперь закрываю файл tmp, а затем снова открываю его, и это, кажется, исправляет все.
tmpFile, err := ioutil.TempFile("", "oriio-")
if err != nil {
return nil, err
}
if _, err := io.Copy(tmpFile, f); err != nil {
return nil, fmt.Errorf("could not copy request body to file %w", err)
}
tmpFile.Close()
tmpFile, err = os.Open(tmpFile.Name())
if err != nil {
panic(err)
}
head := make([]byte, 261)
if _, err := tmpFile.Read(head); err != nil {
return nil, err
}
Теперь, когда я распечатываю массив байтов заголовка, печатается правильное содержимое. Почему это? Есть ли какой-то тип Syn c или Flu sh, который мне нужен для работы с оригинальным файлом tmp?