Your server receives a file (e.g. via a form post), and your server code is responsible to save it to a folder of the server's choice.
The client has no control over where the server will save it. The client may arbitrarily recommend a folder e.g. with another form field (or a subfolder relative to some agreed or arbitrary root), but the client is not in a position to enforce anything.
One thing you should be aware of that if you acquire the posted file name at server side, you should not use it as is, because the client may send a file name which contains folder separators (e.g. '/'
and it may contain sequences to denote parent folders (e.g. "../.."
).
What you should do (most secure) is to generate a name at the server side. Or if you want to use the name recommended by the client, only use the last part of the sent file name (in case it contains folder names too). Also if you use the name sent by the client, you should check if file already exists to prevent independent clients to overwrite each other's files. Or best would be to use a folder name unique to the client, that way there is no chance to overwrite each other's files.
You may use the path
package to check/manipulate file names and paths. For example path.Base()
returns only the last part (the file name) of a path. And you may use path.Join()
to concatenate folders and file name.
For example if a client uploads a file via a form post, you may handle it at server side like this:
func fileHandler(w http.ResponseWriter, r *http.Request) {
f, fh, err := r.FormFile("file")
if err != nil {
// File not submitted? Handle error
http.Error(w, "You must upload a file", http.StatusBadRequest)
return
}
// Save it:
// Here I use username as a unique client identifier
saveName := path.Join("path/to/uploaded/files/", username, path.Base(fh.Filename))
savef, err := os.Create(saveName)
if err != nil {
// Failed to create file on server, handle err
http.Error(w, "Failed to save file", http.StatusInternalServerError)
return
}
defer savef.Close()
io.Copy(savef, f)
fmt.Fprintln(w, "File saved successfully.")
}