File has no content after downloading xlsx file using http/net - go

I tried downloading an Excel file from a URL using http/net by calling the GET method. I don't know if this is releveant, but as for my case, I use dropbox to store the file on the cloud (it's open for public, not restricted, it can be accessed on incognito).
But when I open the file that's saved on the local, it has no content at all. It has just an empty sheet. The file is supposed to have filled with lots of data in cell.
What's happening here? Anyone knows how to solve it? There's no error at all when I print it.
func main() {
filePath := "./file/filename.xlsx"
url := "http://www.dropbox.com/somethingsomething.xlsx"
out, err := os.Create(filePath)
if err != nil {
fmt.Println(err)
}
defer out.Close()
resp, err := http.Get(url)
if err != nil {
fmt.Println(err)
}
defer resp.Body.Close()
_, err = io.Copy(out, resp.Body)
if err != nil {
fmt.Println(err)
}
return
}

Does the dropbox URL have dl=0 query param?
If so, try changing it to dl=1 to force download the file.
I tried the same with one of my files and it worked.
Thanks!

Related

Handle Http Upload Zip file in Golang

I'm using golang net/http package to retrieve the uploaded zip file via postman.
The attachment file link. It is not dangerous file. Feel free to check out.
Development env
local machine m1 macbook pro golang 1.17.2 - no issue
server docker image golang:1.17.5-stretch - got issue.
Code to capture the post form transSourceFile file.
func HandleFileReqTest(w http.ResponseWriter, req *http.Request, params map[string]string) err {
if err := req.ParseMultipartForm(32 << 20); err != nil {
return err
}
file, header, err := req.FormFile("transSourceFile")
if err != nil {
return err
}
defer file.Close()
fmt.Println("header.Size:", header.Size)
return nil
}
I tried below code also no use
func HandleFileReqTest(w http.ResponseWriter, req *http.Request, params map[string]string) err {
if err := req.ParseForm(); err != nil {
return err
}
req.ParseMultipartForm(32 << 20)
file, header, err := req.FormFile("transSourceFile")
if err != nil {
return err
}
defer file.Close()
fmt.Println("header.Size:", header.Size)
return nil
}
Result:
Local machine got the same file size as the origin file.
Server with golang:1.17.5-stretch got the different file size compare to origin file.
As the result on this, i'm unable to unzip the file in the server. Anyone can help?
You need to copy form file to the actual file:
f, err := os.Create("some.zip")
defer f.Close()
n, err := io.Copy(f, file)
Data isn't being flushed to the file completely. You should close the file first to ensure that the data is fully flushed.
// create a local file filename
dst, err := os.Create("filename.zip")
// save it
fl, err = io.Copy(dst, src)
// Close the file
dst.Close()
stat, _ := dst.Stat()
//Now check the size stat.Size() or header.Size after flushing the file.

How to add images into specific folder in Go? Getting error like: `%!(EXTRA *fs.PathError=open /photos: read-only file system)`

I am trying to put images into a specific folder in Golang. Here is the code below.
This is the function where I create a folder called photos in the root directory.
func createPhotoFolder(folderName string) {
err := os.Mkdir(folderName, 777)
if err != nil {
fmt.Println("Error creating folder: ", err)
return
}
fmt.Println(folderName, " created successfully in the root directory")
}
This is the function where I make get request to fetch image and try to put them into a photos folder I created earlier.
func downloadImages(urls []string) {
for i, url := range urls {
resp, err := http.Get(url)
fmt.Printf("%d inside for loop\n", i)
if err != nil {
log.Fatal("error fetching image: ", err)
}
defer resp.Body.Close()
out, err := os.Create("photos")
if err != nil {
log.Printf("Can't put image into folder: ", err)
}
defer out.Close()
}
}
This is the error I get when I run the program.
1- If the folder name is written in this way os.Create("photos") without forwardslash I get the error message as below.
Can't put image into folder: %!(EXTRA *fs.PathError=open photos: is a directory)
2- If I write it like os.Create("/photos"). I get the error as below.
Can't put image into folder: %!(EXTRA *fs.PathError=open /photos: read-only file system)
I gave all the permission while creating the photos folder in the way of chmod.
I did try using io.Copy() but it requires a file parameter which I don't get while creating one using os.Create()
How should I create the folder and put the images inside it properly?
Here, in your code, in os.Create, it should have the complete address of the file to be created along with the name of the file to be created. Like:
gopath := "C:/Users/<username>/go/src/photos/" //where photos is the folder you created
filename := "photo1.jpg"
out, err := os.Create(gopath + filename)
Also, as #steven-penny gave in his answer, create a filename from the image name directly from the url. So that you don't have to give the filename for each image you download.
out, err := os.create(gopath + filepath.Base(link))
And save the image to your system with,
out.Readfrom(resp.Body)
Here is a small program that does what I think you are trying to do:
package main
import (
"net/http"
"os"
"path/filepath"
)
func downloadImages(links []string) error {
tmp := os.TempDir()
for _, link := range links {
println(link)
res, err := http.Get(link)
if err != nil { return err }
defer res.Body.Close()
file, err := os.Create(filepath.Join(tmp, filepath.Base(link)))
if err != nil { return err }
defer file.Close()
file.ReadFrom(res.Body)
}
return nil
}
func main() {
links := []string{
"http://cdn.sstatic.net/Sites/stackoverflow/Img/apple-touch-icon.png",
"http://cdn.sstatic.net/Sites/stackoverflow/Img/favicon.ico",
}
err := downloadImages(links)
if err != nil {
panic(err)
}
}
You'll want to modify it, as you were using a different directory, but it should get you started.
https://golang.org/pkg/os#File.ReadFrom

Editing a zip file in memory

I am trying to edit a zip file in memory in Go and return the zipped file through a HTTP response
The goal is to add a few files to a path in the zip file example
I add a log.txt file in my path/to/file route in the zipped folder
All this should be done without saving the file or editing the original file.
I have implemented a simple version of real-time stream compression, which can correctly compress a single file. If you want it to run efficiently, you need a lot of optimization.
This is only for reference. If you need more information, you should set more useful HTTP header information before compression so that the client can correctly process the response data.
package main
import (
"archive/zip"
"io"
"net/http"
"os"
"github.com/gin-gonic/gin"
)
func main() {
engine := gin.Default()
engine.GET("/log.zip", func(c *gin.Context) {
f, err := os.Open("./log.txt")
if err != nil {
c.String(http.StatusInternalServerError, err.Error())
return
}
defer f.Close()
info, err := f.Stat()
if err != nil {
c.String(http.StatusInternalServerError, err.Error())
return
}
z := zip.NewWriter(c.Writer)
head, err := zip.FileInfoHeader(info)
if err != nil {
c.String(http.StatusInternalServerError, err.Error())
return
}
defer z.Close()
w, err := z.CreateHeader(head)
if err != nil {
c.String(http.StatusInternalServerError, err.Error())
return
}
_, err = io.Copy(w, f)
if err != nil {
c.String(http.StatusInternalServerError, err.Error())
return
}
})
engine.Run("127.0.0.1:8080")
}
So after hours of tireless work i figured out my approach was bad or maybe not possible with the level of my knowledge so here is a not so optimal solution but it works and fill ur file is not large it should be okay for you.
So you have a file template.zip and u want to add extra files, my initial approach was to copy the whole file into memory and edit it from their but i was having complications.
My next approach was to recreate the file in memory, file by file and to do that i need to know every file in the directory i used the code below to get all my files into a list
root := "template"
err = filepath.Walk(root, func(path string, info os.FileInfo, err error) error {
if info.IsDir() {
return nil
}append(files,path)}
now i have all my files and i can create a buffer to hold all this files
buf := new(bytes.Buffer)
// Create a new zip archive.
zipWriter := zip.NewWriter(buf)
now with the zip archive i can write all my old files to it while at the same time copying the contents
for _, file := range files {
zipFile, err := zipWriter.Create(file)
if err != nil {
fmt.Println(err)
}
content, err := ioutil.ReadFile(file)
if err != nil {
log.Fatal(err)
}
// Convert []byte to string and print to screen
// text := string(content)
_, err = zipFile.Write(content)
if err != nil {
fmt.Println(err)
}
}
At this point, we have our file in buf.bytes()
The remaining cold adds the new files and sends the response back to the client
for _, appCode := range appPageCodeText {
f, err := zipWriter.Create(filepath.fileextension)
if err != nil {
log.Fatal(err)
}
_, err = f.Write([]byte(appCode.Content))
}
err = zipWriter.Close()
if err != nil {
fmt.Println(err)
}
w.Header().Set("Content-Disposition", "attachment; filename="+"template.zip")
w.Header().Set("Content-Type", "application/zip")
w.Write(buf.Bytes()) //'Copy' the file to the client

How to upload file which is response of third party API

I am new to Go Programming. I need to upload a file which I am getting from a third party API.
I am getting response as a PDF file from third party API. Now I want to upload this PDF file to a folder. I am not understanding how I can upload that PDF file and not getting any reference.
url := "https://api.xyz.com/v3/files/fcc280cf620204d4bb5dbd6a8cbbbb8fea1a20fc"
client := &http.Client{}
req, err := http.NewRequest("GET", url, nil)
if err != nil {
fmt.Println("Failed")
}
req.Header.Set("Content-Type", "application/json")
req.SetBasicAuth("xxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxxx", "")
resp, err := client.Do(req)
if err != nil {
fmt.Println("ERROR")
}
fmt.Println(resp) // here I am getting pdf file
defer resp.Body.Close()
Please suggest me some reference or some sample code. I am working on this since last few days to complete this task.
It's pretty simple. First, create and open a file using os.Create.
out, err := os.Create("filename.pdf")
if err != nil {
return err
}
defer out.Close()
Next, use io.Copy() to download the content.
_, err = io.Copy(out, resp.Body)
You can take a look at this for reference.

cloud storage: unable to upload any content while local with golang

I have this piece of code:
ctx:=context.Background()
cliente, err := storage.NewClient(ctx)
if err != nil {
log.Fatal(err)
}
clienteCS := cliente.Bucket("prueba123456789")
w:=clienteCS.Object("prueba").NewWriter(ctx)
w.ContentType = "text/plain"
if _, err := w.Write([]byte("abcde\n")); err != nil {
log.Fatal(err)
}
attrs, err := clienteCS.Attrs(ctx)
fmt.Printf("atrr: %+v err:%v\n",attrs,err)
When I run this program, in the console I can see the attributes printed from my bucket, that would mean for me that there is nothing wrong with the configuration
, but the problem is that when I see on console.cloud.google.com I see no file on my bucket even on api dashboard does not seem like any api has been called(that peak before the red line is other api I was using) , even though no error is showing on my console that could indicate something went wrong
I just forgot about closing the client, this page alert this problem, always must close the client or the file won't be send, so just need to add some lines:
if err := w.Close(); err != nil {
log.Fatal(err)
return
}

Resources