Проверка многокомпонентной загрузки файлов в gin-gonic

Я пытаюсь добавить проверку для веб-приложения на основе Go, основанного на структуре GIN. На веб-странице я выбираю файл и отправляю его, а сервер его обрабатывает. На стороне сервера я пытаюсь добавить проверку, чтобы проверить, был ли предоставлен файл или нет. Если нет, то перенаправьте обратно на исходную страницу.

    func panic(err error)  {
        if err != nil {
            log.Println(err)
        }
    }

    func displayTable (c *gin.Context) {    
    file, _ , err := c.Request.FormFile("file")
    panic(err)
    if file == nil {
        log.Println("File is nil.")
        log.Println(err)
        log.Println("*****")
        c.HTML(http.StatusInternalServerError, "index.tmpl", gin.H{
            "title": "Select the input file","error" : "Please select the input file.",
        })      
    } else {
        defer file.Close()
    }
    filename := strconv.FormatInt(time.Now().Unix(),10) 
    out, err := os.Create("./tmp/"+filename+".xml")
    panic(err)
    defer out.Close()
    _, err = io.Copy(out, file)
    panic(err)
    xmlFile, err := os.Open("./tmp/"+filename+".xml")
    panic(err)
    defer xmlFile.Close()

    // Other Implementation Details 
}

Даже после предоставления обработки я получаю панику в коде go. Пожалуйста, дайте мне знать, что мне не хватает в реализации.

Спасибо.

    http: no such file
    File is nil.
    http: no such file
    *****
    2015/08/04 13:19:10 Panic recovery -> runtime error: invalid memory address or nil pointer dereference
    c:/go/src/runtime/panic.go:387 (0x414d36)
    c:/go/src/runtime/panic.go:42 (0x4142a5)
    c:/go/src/runtime/os_windows.go:42 (0x414066)
    c:/go/src/io/io.go:362 (0x45268f)
    D:/code/src/exmp/serverexmaple.go:45 (0x40168f)
            displayTable: _, err = io.Copy(out, file)
    D:/code/src/github.com/gin-gonic/gin/context.go:95 (0x49f8ea)
            (*Context).Next: c.handlers[c.index](c)
    D:/code/src/github.com/gin-gonic/gin/logger.go:56 (0x4ac490)
            func.007: c.Next()
    D:/code/src/github.com/gin-gonic/gin/context.go:95 (0x49f8ea)
            (*Context).Next: c.handlers[c.index](c)
    D:/code/src/github.com/gin-gonic/gin/recovery.go:43 (0x4acc80)
            func.009: c.Next()
    D:/code/src/github.com/gin-gonic/gin/context.go:95 (0x49f8ea)
            (*Context).Next: c.handlers[c.index](c)
    D:/code/src/github.com/gin-gonic/gin/gin.go:292 (0x4a46d5)
            (*Engine).handleHTTPRequest: context.Next()
    D:/code/src/github.com/gin-gonic/gin/gin.go:273 (0x4a4459)
            (*Engine).ServeHTTP: engine.handleHTTPRequest(c)
    c:/go/src/net/http/server.go:1703 (0x468415)
    c:/go/src/net/http/server.go:1204 (0x466408)
    c:/go/src/runtime/asm_386.s:2287 (0x438ea1)

person Kunal Jha    schedule 04.08.2015    source источник
comment
Вы должны gofmt свой код и фактически включить то, что у вас есть, это не может быть вашим настоящим кодом: file, _ , err := c.Request.FormFile("file"); panic(err) В любом случае, ошибка довольно очевидна, 2015/08/04 13:19:10 Panic recovery -> runtime error: invalid memory address or nil pointer dereference вы, скорее всего, пытаетесь разыменовать nil.   -  person user3591723    schedule 04.08.2015
comment
@ user3591723 Если вы видите ошибку D:/code/src/exmp/serverexmaple.go:45 (0x40168f) displayTable: _, err = io.Copy(out, file), которая совпадает с кодом, это проблемная область. Проблема в том, что когда значение файла равно нулю, оно не перенаправляет на страницу с ошибкой, а выполняет остальную часть кода и, следовательно, вызывает панику при попытке прочитать нулевое значение. Это обычное поведение для фреймворка джин?   -  person Kunal Jha    schedule 04.08.2015
comment
Я не уверен, что обычно происходит с джином, почему бы просто не вернуться из своей функции? Кроме того, почему вы переопределяете _1 _? .. Это встроенная функция, и для удобства чтения важно не переопределять ее.   -  person user3591723    schedule 04.08.2015


Ответы (2)


  1. Пожалуйста, не переопределяйте panic. Это запутает всех, кто знает, как panic работает.
  2. Сравнение с nil в Go немного сложно. Это может работать не так, как вы ожидаете: Проверьте интерфейс на nil и nil в Go. FormFile возвращает интерфейс, поэтому вам нужно преобразовать его в базовую структуру, если вы хотите проверить его с помощью nil, ИЛИ используйте второй параметр, тип которого доступен.
  3. Это не относится к GIN, это часть реализации HTTP в Go: http://golang.org/pkg/net/http/#Request.FormFile
person Alex Netkachov    schedule 04.08.2015
comment
Спасибо за пункт №1 и пункт №2, о котором мы будем помнить в будущем. Но если я добавлю оператор return после `c.HTML (http.StatusInternalServerError, index.tmpl, gin.H {title: выберите входной файл, ошибка: выберите входной файл.,})` Паника не отображается и перенаправление похоже работает. - person Kunal Jha; 04.08.2015
comment
Ха, очевидно! В исходном коде вы проверяете, что файл равен нулю, и вызываете _, err = io.Copy(out, file), даже если он равен нулю. Конечно вам должна быть добавлена ​​отдача. - person Alex Netkachov; 04.08.2015

Я понимаю, что ошибся с обработкой panic. Проверка работает, если я добавлю оператор return после c.HTML. Это остановит выполнение функции остальной части кода. Спасибо @AlexAtNet за его совет, и я буду помнить об этом в будущем.

if file == nil {
    log.Println("File is nil.")
    log.Println(err)
    log.Println("*****")
    c.HTML(http.StatusInternalServerError, "index.tmpl", gin.H{
        "title": "Select the input file","error" : "Please select the input file.",
    })   
    return 
} 
person Kunal Jha    schedule 05.08.2015