Golang io.Copy() does not copy the file in Linux (CentOS)

1,687 views
Skip to first unread message

md5l...@gmail.com

unread,
Sep 23, 2015, 10:16:59 AM9/23/15
to golang-nuts

I'm new to Go. The following code works perfectly in windows, but not on CentOS. I receive a multipart file from the client. The file has the correct size and there are no errors in reading it.


I need to create specific directories for the uploading user and save the files in there. 

Directories are created just fine, but the file is not written. This whole code runs with no errors on any stage. I'm using Go v1.5.1 and BeeGo framework.


Here's the code:


file , header , err := this.GetFile( "logo" );

    defer func(){
        err := file.Close()
        if err != nil {
            fmt.Println( err.Error() )
        }
    }()


    size , seekErr := file.Seek( 0 , 2 )
    maxSize , _ := beego.AppConfig.Int64( "MaxSize" )

    if err != nil {

        response.Data = err.Error()
        response.Success = false

    } else if seekErr != nil {

        response.Data = seekErr.Error()
        response.Success = false

    } else if size > maxSize {

        response.Data = "File too large: " + string(size)
        response.Success = false

    } else {

        if _ , errDE := os.Stat( "static/media/business" ) ; os.IsNotExist( errDE ){
            os.Mkdir( "static/media/business" , os.ModeDir )
            os.Chmod( "static/media/business" , 0755 )
        }

        offset , err := file.Seek( 0 , 0 )

        if err != nil {
            fmt.Println( "Error seeking: " + err.Error() )
        }

        path := "static/media/business/" + u.( models.User ).Business.BusinessPage

        if _ , errDE := os.Stat( path ) ; os.IsNotExist( errDE ){
            os.Mkdir( path , os.ModeDir )
            os.Chmod( path , 0755 )
        }

        name := files.GenerateFileName( header.Filename , 24 )

        out , err := os.Create( path + "/" + name )

        if err != nil {

            response.Data = err.Error()
            response.Success = false

        } else {

            defer func(){
                err := out.Close()
                if err != nil {
                    fmt.Println( err.Error() )
                }
            }()

            _ , err = io.Copy( out , file )
            os.Chmod( path + "/" + name , 0755 )
            ...



Is there something I'm missing?

If that's not the forum for such questions - please let me know.

silviun...@gmail.com

unread,
Sep 23, 2015, 10:28:27 AM9/23/15
to golang-nuts, md5l...@gmail.com
Hey, make sure that error at your final commands io.Copy and chmod are also checked
(in essence if you leave anything that returns an error unchecked expect your code to break and you to be left scratching your head)

_ , err = io.Copy( out , file )
if err != nil { fmt.Println("ALAAAAAAAAAARM: ", err) }
chmodError := os.Chmod( path + "/" + name , 0755 )
if chmodError != nil { fmt.Println("CHMOD ALAAAAAAAAAARM: ", err) }

md5l...@gmail.com

unread,
Sep 23, 2015, 10:38:07 AM9/23/15
to golang-nuts, md5l...@gmail.com
I'm checking the err in _ , err = io.Copy( out , file ) and it is nil. The chmod afterwards is irrelevant, since no file is copied in io.Copy(). There is a whole bunch of code which is not shown here that runs after the copy (DB update, model manipulations, etc.) that executes just fine under the condition of err == nil, so it is.

среда, 23 сентября 2015 г., 17:16:59 UTC+3 пользователь md5l...@gmail.com написал:

roger peppe

unread,
Sep 23, 2015, 11:32:39 AM9/23/15
to md5l...@gmail.com, golang-nuts
Please make a small self-contained example that you can
use to reproduce the error. There is a lot of context implicit in the
example you've got
that makes it hard to answer your question.

Some immediate suggestions (that probably won't solve your problem
but will make the code better):

- check the error from the GetFile method before deferring the Close
or calling Seek.

- return an error rather than setting the response fields all over the
place. This enables you to return early and keep indentation level smaller
and makes the code easier to reason about.

- it's probably not worthwhile checking the return values from the
two Close calls - if you get an error when closing a file, you've already
written all the data (files aren't buffered locally), so you don't care much.

- just a style point, but "this" isn't considered a good name for a receiver
variable - just use the same variable name you'd use for any instance of
the type - the receiver parameter is just a parameter.

- always gofmt your code.

Some of these suggestions implemented: http://play.golang.org/p/pXfOx4Bdtr

cheers,
rog.
> --
> You received this message because you are subscribed to the Google Groups
> "golang-nuts" group.
> To unsubscribe from this group and stop receiving emails from it, send an
> email to golang-nuts...@googlegroups.com.
> For more options, visit https://groups.google.com/d/optout.

Dustin

unread,
Sep 23, 2015, 11:44:32 AM9/23/15
to golang-nuts
Just for a test, you could io.Copy(os.Stdout, file) to see what data is being read from the file. And use io.WriteString(out, "some data") to see if data is being written to out. This will help isolate the issue.

md5l...@gmail.com

unread,
Sep 23, 2015, 11:46:39 AM9/23/15
to golang-nuts, md5l...@gmail.com
1. The code is "fmt"ed everywhere it is possible, but for readability reasons those line were not included.
2. GetFile, Seek, Copy, Chmod, Create, etc. run with no errors.
3. The deferred Close check is only to trace possible crashes, no for the production.
4. I cannot return an error since there are no errors at the runtime. That's what it is all about. I just cannot get any errors, but the file is not copied.

среда, 23 сентября 2015 г., 17:16:59 UTC+3 пользователь md5l...@gmail.com написал:

I'm new to Go. The following code works perfectly in windows, but not on CentOS. I receive a multipart file from the client. The file has the correct size and there are no errors in reading it.

Volker Dobler

unread,
Sep 23, 2015, 12:16:10 PM9/23/15
to golang-nuts, md5l...@gmail.com
Then maybe you are doing something else differently?
Invoke the wrong binary? Peek at the wrong folder?

V.

roger peppe

unread,
Sep 23, 2015, 12:22:39 PM9/23/15
to md5l...@gmail.com, golang-nuts
On 23 September 2015 at 16:46, <md5l...@gmail.com> wrote:
> 1. The code is "fmt"ed everywhere it is possible, but for readability
> reasons those line were not included.

It's worth just gofmt'ing *all* your Go code (go fmt ./...
in your top level directory). The output of gofmt is
considered to be the definition of "readable" in Go.

> 2. GetFile, Seek, Copy, Chmod, Create, etc. run with no errors.
> 3. The deferred Close check is only to trace possible crashes, no for the
> production.
> 4. I cannot return an error since there are no errors at the runtime. That's
> what it is all about. I just cannot get any errors, but the file is not
> copied.

Did you look at the example code I pointed to? I'm suggesting that
you return an error from your method, but convert it as required
in the caller (by putting the message in the response).

Can you reproduce this problem reliably? If so, please make
a small example that you can share with us so that we
can find out where the bug lies.

cheers,
rog.

Kiki Sugiaman

unread,
Sep 23, 2015, 12:22:59 PM9/23/15
to golan...@googlegroups.com
Because of incomplete information, take the following as troubleshooting
idea (yes, it's a guess).

How do you check that the file is not copied? The file contents may not
be there before the file is closed or flushed (out.Sync() ).
Technically, you also should not perform any modification [other than
the stream manipulation] to the file before it is closed. So, it's
better if os.Chmod is inside your defer block after out.Close and its
error handling.

Tamás Gulácsi

unread,
Sep 23, 2015, 1:32:28 PM9/23/15
to golang-nuts
Please check the error of the Close() of the just written file!
Buffering can trick you!

roger peppe

unread,
Sep 24, 2015, 2:54:50 AM9/24/15
to Tamás Gulácsi, golang-nuts
On 23 September 2015 at 18:32, Tamás Gulácsi <tgula...@gmail.com> wrote:
> Please check the error of the Close() of the just written file!
> Buffering can trick you!

Assuming the file is an *os.File, I don't believe that's true, because
it does no buffering. Do you know of a real situation where Close
on a *os.File can indicate that the file was not written correctly?

cheers,
rog.

Tamás Gulácsi

unread,
Sep 24, 2015, 6:57:23 AM9/24/15
to golang-nuts
No, the only clue given is differing OS. So why not differing buffering or fs or anything os-related?

md5l...@gmail.com

unread,
Sep 24, 2015, 3:08:31 PM9/24/15
to golang-nuts, md5l...@gmail.com
Thanks for all your responses, guys!

It appears that I can io.Copy to *.txt file under the mentioned path, but not to *.png or *.jpg.

среда, 23 сентября 2015 г., 17:16:59 UTC+3 пользователь md5l...@gmail.com написал:

I'm new to Go. The following code works perfectly in windows, but not on CentOS. I receive a multipart file from the client. The file has the correct size and there are no errors in reading it.

md5l...@gmail.com

unread,
Sep 24, 2015, 3:22:06 PM9/24/15
to golang-nuts, md5l...@gmail.com
Update:

Not only any file other than *.txt is not created, but renaming a *.jpg.txt to *.jpg deletes the *.txt file.


среда, 23 сентября 2015 г., 17:16:59 UTC+3 пользователь md5l...@gmail.com написал:

I'm new to Go. The following code works perfectly in windows, but not on CentOS. I receive a multipart file from the client. The file has the correct size and there are no errors in reading it.

Reply all
Reply to author
Forward
0 new messages