Golang how can I get full file path - go

I been searching around and can not find a way to get the full file path in Go . I have a regular html form and then I try to get all the information in the backend
<form method="post" enctype="multipart/form-data" action="/uploads">
<p><input type="file" name="my file" id="my file"></p>
<p>
<input type="submit" value="Submit">
</p>
func upload() {
f,h,err := r.FormFile("my file")
if err != nil {
log.Println(err)
http.Error(w,"Error Uploading",http.StatusInternalServerError)
return
}
defer f.Close()
println(h.Filename)
}
// This gets me the name of the file, I would like the full path of it
I have tried file path.dir() but that does not do anything

here is an example:
package main
import (
"fmt"
"path/filepath"
)
func main() {
abs,err := filepath.Abs("./hello.go")
if err == nil {
fmt.Println("Absolute:", abs)
}
}

As far as I know, you cannot get the filepath form the f value in your code. Because the file data is not stored in disk yet.
And you want to store the file to a path, you can do it this way.
f,h,err := r.FormFile("myfile")
if err != nil{
log.Println("err: ",err)
http.Error(w,"Error Uploading",http.StatusInternalServerError)
return
}
defer f.Close()
fmt.Println("filename: ",h.Filename)
bytes, err := ioutil.ReadAll(f)
if err != nil {
fmt.Println(err)
}
filepath := "./aa" //set your filename and filepath
err = ioutil.WriteFile("aa", bytes, 0777)
if err != nil {
fmt.Println(err)
}

Related

Golang: Facing error while creating .tar.gz file having large name

I am trying to create a .tar.gz file from folder that contains multiple files / folders. Once the .tar.gz file gets created, while extracting, the files are not not properly extracted. Mostly I think its because of large names or path exceeding some n characters, because same thing works when the filename/path is small. I referred this https://github.com/golang/go/issues/17630 and tried to add below code but it did not help.
header.Uid = 0
header.Gid = 0
I am using simple code seen below to create .tar.gz. The approach is, I create a temp folder, do some processing on the files and from that temp path, I create the .tar.gz file hence in the path below I am using pre-defined temp folder path.
package main
import (
"archive/tar"
"compress/gzip"
"fmt"
"io"
"log"
"os"
fp "path/filepath"
)
func main() {
// Create output file
out, err := os.Create("output.tar.gz")
if err != nil {
log.Fatalln("Error writing archive:", err)
}
defer out.Close()
// Create the archive and write the output to the "out" Writer
tmpDir := "C:/Users/USERNAME~1/AppData/Local/Temp/temp-241232063"
err = createArchive1(tmpDir, out)
if err != nil {
log.Fatalln("Error creating archive:", err)
}
fmt.Println("Archive created successfully")
}
func createArchive1(path string, targetFile *os.File) error {
gw := gzip.NewWriter(targetFile)
defer gw.Close()
tw := tar.NewWriter(gw)
defer tw.Close()
// walk through every file in the folder
err := fp.Walk(path, func(filePath string, info os.FileInfo, err error) error {
// ensure the src actually exists before trying to tar it
if _, err := os.Stat(filePath); err != nil {
return err
}
if err != nil {
return err
}
if info.IsDir() {
return nil
}
file, err := os.Open(filePath)
if err != nil {
return err
}
defer file.Close()
// generate tar header
header, err := tar.FileInfoHeader(info, info.Name())
header.Uid = 0
header.Gid = 0
if err != nil {
return err
}
header.Name = filePath //strings.TrimPrefix(filePath, fmt.Sprintf("%s/", fp.Dir(path))) //info.Name()
// write header
if err := tw.WriteHeader(header); err != nil {
return err
}
if _, err := io.Copy(tw, file); err != nil {
return err
}
return nil
})
return err
}
Please let me know what wrong I am doing.

Filling out the form fields in docx using golang library unioffice

I'm trying to fill out the form fields using unioffice library. The document that i'm working with, contains several paragraphs. The paragraphs contains several form fields.
I want to fill out all of the form fields in the document. And here is the code i'm running:
doc, err := document.Open("form.docx")
if err != nil {
log.Fatalf("error opening form: %s", err)
}
for i := range doc.FormFields() {
doc.FormFields()[i].SetValue("test")
}
doc.SaveToFile("filled-form.docx")
However, not all of the form fields were filled out.
Looks to me like a bug in func (d *Document) Save(w io.Writer) error{}. I can read and write to every of the FormFields but only the last FormField value in the paragraph gets actually saved to the file.
Below code works like expected until you save to file. (That means it prints out the previously set value). I saw you already opened a new issue on github (link) i hope you have more luck with that.
package main
import (
"github.com/unidoc/unioffice/document"
"io/ioutil"
"log"
"os"
)
func main() {
_, err := ioutil.ReadFile("filled-form.docx")
if err == nil {
err = os.Remove("filled-form.docx")
if err != nil {
log.Fatal(err)
}
}
doc, err := document.Open("form.docx")
if err != nil {
log.Fatalf("error opening form: %s", err)
}
for _, f := range doc.FormFields() {
if f.Type() == document.FormFieldType(1) {
f.SetValue("test")
}
}
for _, f := range doc.FormFields() {
log.Println("-------------------")
log.Println(f.Name())
log.Println(f.Value())
}
err = doc.SaveToFile("filled-form.docx")
if err != nil {
log.Fatal(err)
}
}

How to write RIFF chunk header when store image from url?

I just tried to download webp image from url, but I found something different when I try to process the stored image.
If I download the image from the browser, it can be decoded using x/image/webp package, but if I store the image using http.Get() then create a new file then io.Copy() the image, it says:
"missing RIFF chunk header"
I assume that I need to write some RIFF chunk header when I store it using golang code.
func main(){
response, e := http.Get(URL)
if e != nil {
log.Fatal(e)
}
defer response.Body.Close()
//open a file for writing
file, err := os.Create('tv.webp')
if err != nil {
log.Fatal(err)
}
defer file.Close()
// Use io.Copy to just dump the response body to the file. This supports huge files
_, err = io.Copy(file, response.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println("Success!")
imgData, err := os.Open("tv.webp")
if err != nil {
fmt.Println(err)
return
}
log.Printf("%+v", imgData)
image, err := webp.Decode(imgData)
if err != nil {
fmt.Println(err)
return
}
fmt.Println(image.Bounds())
}
Here is the URL IMG URL
download file is not webp type. it's png.
package main
import (
"fmt"
"image"
"io"
"log"
"net/http"
"os"
_ "image/png"
)
func main() {
response, e := http.Get("https://www.sony.com/is/image/gwtprod/0abe7672ff4c6cb4a0a4d4cc143fd05b?fmt=png-alpha")
if e != nil {
log.Fatal(e)
}
defer response.Body.Close()
file, err := os.Create("dump")
if err != nil {
log.Fatal(err)
}
defer file.Close()
_, err = io.Copy(file, response.Body)
if err != nil {
log.Fatal(err)
}
fmt.Println("Success!")
imageFile, err := os.Open("dump")
if err != nil {
panic(err)
}
m, name, err := image.Decode(imageFile)
if err != nil {
panic(err)
}
fmt.Println("image type is ", name, m.Bounds())
}

Unable to delete an unzipped folder using golang

I wrote code that unzips a file in a particular location then copies the contents of the folder to outside where the folder is unzipped then it removes the folder.
This is the Code I wrote:
package main
import (
"os"
"flag"
"fmt"
"io"
"path/filepath"
"os/exec"
"archive/zip"
"time"
)
func RemoveContents(dir string) error {
d, err := os.Open(dir)
if err != nil {
return err
}
names, err := d.Readdirnames(-1)
if err != nil {
return err
}
for _, name := range names {
err = os.RemoveAll(filepath.Join(dir, name))
if err != nil {
return err
}
}
d.Close()
return nil
}
func CopyFile(source string, dest string) (err error) {
sourcefile, err := os.Open(source)
if err != nil {
return err
}
defer sourcefile.Close()
destfile, err := os.Create(dest)
if err != nil {
return err
}
defer destfile.Close()
_, err = io.Copy(destfile, sourcefile)
if err == nil {
sourceinfo, err := os.Stat(source)
if err != nil {
err = os.Chmod(dest, sourceinfo.Mode())
}
}
return
}
func CopyDir(source string, dest string) (err error) {
// get properties of source dir
sourceinfo, err := os.Stat(source)
if err != nil {
return err
}
// create dest dir
err = os.MkdirAll(dest, sourceinfo.Mode())
if err != nil {
return err
}
directory, _ := os.Open(source)
objects, err := directory.Readdir(-1)
for _, obj := range objects {
sourcefilepointer := source + "/" + obj.Name()
destinationfilepointer := dest + "/" + obj.Name()
if obj.IsDir() {
// create sub-directories - recursively
err = CopyDir(sourcefilepointer, destinationfilepointer)
if err != nil {
fmt.Println(err)
}
} else {
// perform copy
err = CopyFile(sourcefilepointer, destinationfilepointer)
if err != nil {
fmt.Println(err)
}
}
}
return
}
func main() {
flag.Parse() // get the source and destination directory
source_dir := flag.Arg(0) // get the source directory from 1st argument
dest_dir := flag.Arg(1) // get the destination directory from the 2nd argument
os.MkdirAll("E:\\go\\copyDirectory\\myFile.zip",0777)
zipFilePath := "E:\\go\\copyDirectory\\myFile.zip"
tempWrkDir := "E:\\go\\copyDirectory\\"
//Read zip file and get path handle.
fileHandleReader, err := zip.OpenReader(zipFilePath)
if err != nil {
fmt.Println(err)
os.Exit(1)
}
//open zip file and read all the folder and files inside
for _, fileReadHandler := range fileHandleReader.Reader.File {
//read the file or folder handle inside zip
fileOpenHandle, err := fileReadHandler.Open()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
defer fileOpenHandle.Close()
targetUnZipPath := filepath.Join(tempWrkDir, fileReadHandler.Name)
if fileReadHandler.FileInfo().IsDir() {
os.MkdirAll(targetUnZipPath, fileReadHandler.Mode())
//fmt.Println("Creating directory", path)
}else {
// create new dummy file to copy original file.
newTempFileHandle, err := os.OpenFile(targetUnZipPath, os.O_WRONLY|os.O_CREATE, fileReadHandler.Mode())
if err != nil {
fmt.Println(err)
os.Exit(1)
}
defer newTempFileHandle.Close()
//copying original file to dummy file.
if _, err = io.Copy(newTempFileHandle, fileOpenHandle); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
}
time.Sleep(1000*time.Millisecond)
fmt.Println("Source :" + source_dir)
// check if the source dir exist
src, err := os.Stat(source_dir)
if err != nil {
panic(err)
}
if !src.IsDir() {
fmt.Println("Source is not a directory")
os.Exit(1)
}
// create the destination directory
fmt.Println("Destination :"+ dest_dir)
/*_, err = os.Open(dest_dir)
if !os.IsNotExist(err) {
fmt.Println("Destination directory already exists. Abort!")
os.Exit(1)
}*/
err = CopyDir(source_dir, dest_dir)
if err != nil {
fmt.Println(err)
} else {
fmt.Println("Directory copied")
}
err = RemoveContents("./myFiles")
if err != nil {
fmt.Println("ERRR:::",err)
}
//time.Sleep(10000*time.Millisecond)
}
The problem is that everything works fine except for deleting the folder. The folder has only one file in it. The location of the file is as follows:
E:\go\copyDirectory\myfile\mytextfile.txt
The Location of the zip file is as follows:
E:\go\copyDirectory\myfile.zip
The zip file has only one text file. The File inside the zip file is as follows:
E:\go\copyDirectory\myfile.zip\myfile\mytextfile.txt
The error I get is:
ERRR::: remove myfile\mytextfile.txt: The process cannot
access the file because it is being used by another process.
Thanks in advance.
You aren't closing the file. This:
defer newTempFileHandle.Close()
Is run when main finishes, which is after:
err = RemoveContents("./myFiles")
You can wrap that bit of code in an unnamed function:
func() {
//read the file or folder handle inside zip
fileOpenHandle, err := fileReadHandler.Open()
if err != nil {
fmt.Println(err)
os.Exit(1)
}
defer fileOpenHandle.Close()
targetUnZipPath := filepath.Join(tempWrkDir, fileReadHandler.Name)
if fileReadHandler.FileInfo().IsDir() {
os.MkdirAll(targetUnZipPath, fileReadHandler.Mode())
//fmt.Println("Creating directory", path)
} else {
// create new dummy file to copy original file.
newTempFileHandle, err := os.OpenFile(targetUnZipPath, os.O_WRONLY|os.O_CREATE, fileReadHandler.Mode())
if err != nil {
fmt.Println(err)
os.Exit(1)
}
defer newTempFileHandle.Close()
//copying original file to dummy file.
if _, err = io.Copy(newTempFileHandle, fileOpenHandle); err != nil {
fmt.Println(err)
os.Exit(1)
}
}
}()
And then your defer will happen before you try and remove the files. I would recommend pulling this out into a named function though.

HTTP-POST file multipart

I'm trying to send a multipart form using Go packages mime/multipart and http, and I need some help to solve it.
The HTML would be:
<html>
<head><title>Multipart Test</title></head>
<body>
<form action="/multipart" enctype="multipart/form-data" method="POST">
<label for="file"> Please select a File </label>
<input id="file" type="file" name="file"/>
<br>
<label for="input1"> Please write some text </label>
<input id="input1" type="text" name="input1"/>
<br>
<label for="input2"> Please write some more text </label>
<input id="input2" type="text" name="input2"/>
<br>
<input type="submit" name="Submit" value="Submit"/>
</body>
And my Go approach is like this:
var buffer bytes.Buffer
w := multipart.NewWriter(&buffer)
// Write fields and files
w.CreateFormField("input1")
w.WriteField("input1","value1")
w.CreateFormFile("file","filename.dat")
// I need a Reader to here to read the file, but how ?
// then send the request
resp,err := http.Post(url,w.FormDataContentType(),&buffer)
The answer can be found following this sample code
// Upload file to google code
func Upload(tarball string) (err os.Error) {
// Create buffer
buf := new(bytes.Buffer) // caveat IMO dont use this for large files, \
// create a tmpfile and assemble your multipart from there (not tested)
w := multipart.NewWriter(buf)
// Create a form field writer for field label
label, err := w.CreateFormField("label")
if err != nil {
return err
}
// Write label field
label.Write([]byte("label here"))
// Create a form field writer for field summary
summary, err := w.CreateFormField("summary")
if err != nil {
return err
}
// Write summary field
summary.Write([]byte("summary here"))
// Create file field
fw, err := w.CreateFormFile("upload", tarball)
if err != nil {
return err
}
fd, err := os.Open(tarball)
if err != nil {
return err
}
defer fd.Close()
// Write file field from file to upload
_, err = io.Copy(fw, fd)
if err != nil {
return err
}
// Important if you do not close the multipart writer you will not have a
// terminating boundry
w.Close()
req, err := http.NewRequest("POST", repoUrl, buf)
if err != nil {
return err
}
req.Header.Set("Content-Type", w.FormDataContentType())
req.SetBasicAuth("email#email.com", "password")
res, err := client.Do(req)
if err != nil {
return err
}
io.Copy(os.Stderr, res.Body) // Replace this with Status.Code check
return err
}

Resources