Вывод в http файла .mp4, проблема с извлечением из базы данных в браузер

ответил

Мне трудно работать с Mongodb и Gridfs, используя его с http-пакетом Go. Я пытаюсь сохранить файл .mp4 в Gridfs, а затем извлечь его в браузер для воспроизведения.

Вот что я делаю сейчас. Он успешно извлекает файл из базы данных, я даже мог правильно записать его в место загрузки.

// Connect to database
// Session to database

func movie(w http.ResponseWriter r *http.Request) {
    file, err := db.GridFS("fs").Open("movie.mp4")
    if err != nil {
        log.Println(err)
    }
    defer file.Close()

    w.Header.Set("Content-type", "video/mp4")
    if _, err := io.Copy(w, file); err != nil {
    log.Println(err)
    } 
    // I am trying to send it to the browser.
    // I want to achieve same thing as, http://localhost/view/movie.mp4, 
    as if you did that.
}

Если бы файл был на сервере, я бы просто сделал что-то вроде этого. Но вместо этого я пытаюсь сохранить его в Mongodb, чтобы упростить использование метаданных.

func movie(w http.ResponseWriter r *http.Request) {
    http.ServeFile("./uploads/movie.mp4") // Easy
}

Браузер что-то получает, но оно просто искажено или повреждено. Просто показывает видеоплеер с сообщением об ошибке. Буду признателен за любую помощь, я программирую всего неделю.

Вот изображение ошибки, сообщений об ошибках консоли нет.

введите здесь описание изображения

Если только у кого-то нет альтернативы хранению видеофайлов для воспроизведения в браузере где-то кроме MongoDB или Amazon S3. Пожалуйста дайте мне знать, спасибо.


person ABC    schedule 26.12.2017    source источник
comment
Пожалуйста, покажите ошибку веб-консоли.   -  person Зелёный    schedule 26.12.2017
comment
Я загрузил картинку ошибки, Браузер - сафари. У него нет сообщений об ошибках консоли. Я не знаю, почему это происходит, но если я выполню http.ServeFile(.mp4), вы можете посетить URL-адрес /video.mp4, и он загрузит проигрыватель Safari по умолчанию.   -  person ABC    schedule 26.12.2017
comment
Это io.Copy(w, r) опечатка, верно? На самом деле вы не пытаетесь написать запрос в ответ, а file, верно?   -  person mkopriva    schedule 26.12.2017
comment
И, пожалуйста, проверьте ошибку, возвращенную io.Copy.   -  person mkopriva    schedule 26.12.2017
comment
io.Copy не содержит ошибок, и io.Copy не является опечаткой. Я новичок, и я думал, что должен сделать это, чтобы записать файл в браузер. Я хочу, чтобы файл, написанный в ответ, и иметь возможность играть.   -  person ABC    schedule 26.12.2017
comment
Сделайте это вместо этого: if _, err := io.Copy(w, file); err != nil { // handle error   -  person mkopriva    schedule 26.12.2017
comment
Я добавил, что если ваша обработка ошибок все еще не отправляет файл в ответе правильно. Это должно быть проблема с браузером, может быть, что-то с заголовками?   -  person ABC    schedule 26.12.2017
comment
r — это не файл, r — это запрос, который вы получили от клиента, копировать его в w не имеет особого смысла.   -  person mkopriva    schedule 26.12.2017
comment
О, если я сделал это, извините, я неправильно набрал его из-за переполнения стека. Но, да были выписывает в браузер не запрос. Нужно ли сначала читать байты и декодировать их, а затем отправлять? Я бы даже не знал, с чего начать. Я думаю, что это должно быть проблема с заголовком, с content-length и байтами.   -  person ABC    schedule 26.12.2017
comment
Попробуйте решение из этого вопроса: stackoverflow.com /вопросы/38069584/   -  person mkopriva    schedule 26.12.2017
comment
Я не могу использовать ServeFile, потому что использую базу данных.   -  person ABC    schedule 26.12.2017


Ответы (1)


Вы можете проверить http.ServeContent. Он будет обрабатывать весь беспорядок (тип контента, длина контента, частичные данные, кеш) автоматически и сэкономит вам много времени. Для обслуживания требуется ReadSeeker, который уже реализован в GridFile. Таким образом, ваш код может просто измениться на приведенный ниже.

func movie(w http.ResponseWriter r *http.Request) {
    file, err := db.GridFS("fs").Open("movie.mp4")
    if err != nil {
        log.Println(err)
    }
    defer file.Close()

    http.ServeContent(w,r,"movie.mp4",file.UploadDate(),file)

}

Если это не сработает, используйте такие инструменты, как curl или wget, чтобы загрузить предоставленный контент и сравнить его с оригинальным (в БД).

person leaf bebop    schedule 27.12.2017