zip archive download

release/v1.15
slene 2014-04-16 00:27:29 +08:00
parent 5378bb326b
commit 4fafc76052
4 changed files with 112 additions and 32 deletions

View File

@ -10,8 +10,10 @@ import (
"encoding/base64" "encoding/base64"
"fmt" "fmt"
"html/template" "html/template"
"io"
"net/http" "net/http"
"net/url" "net/url"
"path/filepath"
"strconv" "strconv"
"strings" "strings"
"time" "time"
@ -62,7 +64,7 @@ type Context struct {
HTTPS string HTTPS string
Git string Git string
} }
*models.Mirror Mirror *models.Mirror
} }
} }
@ -243,6 +245,41 @@ func (ctx *Context) CsrfTokenValid() bool {
return true return true
} }
func (ctx *Context) ServeFile(file string, names ...string) {
var name string
if len(names) > 0 {
name = names[0]
} else {
name = filepath.Base(file)
}
ctx.Res.Header().Set("Content-Description", "File Transfer")
ctx.Res.Header().Set("Content-Type", "application/octet-stream")
ctx.Res.Header().Set("Content-Disposition", "attachment; filename="+name)
ctx.Res.Header().Set("Content-Transfer-Encoding", "binary")
ctx.Res.Header().Set("Expires", "0")
ctx.Res.Header().Set("Cache-Control", "must-revalidate")
ctx.Res.Header().Set("Pragma", "public")
http.ServeFile(ctx.Res, ctx.Req, file)
}
func (ctx *Context) ServeContent(name string, r io.ReadSeeker, params ...interface{}) {
modtime := time.Now()
for _, p := range params {
switch v := p.(type) {
case time.Time:
modtime = v
}
}
ctx.Res.Header().Set("Content-Description", "File Transfer")
ctx.Res.Header().Set("Content-Type", "application/octet-stream")
ctx.Res.Header().Set("Content-Disposition", "attachment; filename="+name)
ctx.Res.Header().Set("Content-Transfer-Encoding", "binary")
ctx.Res.Header().Set("Expires", "0")
ctx.Res.Header().Set("Cache-Control", "must-revalidate")
ctx.Res.Header().Set("Pragma", "public")
http.ServeContent(ctx.Res, ctx.Req, name, modtime, r)
}
type Flash struct { type Flash struct {
url.Values url.Values
ErrorMsg, SuccessMsg string ErrorMsg, SuccessMsg string

68
routers/repo/download.go Normal file
View File

@ -0,0 +1,68 @@
// Copyright 2014 The Gogs Authors. All rights reserved.
// Use of this source code is governed by a MIT-style
// license that can be found in the LICENSE file.
package repo
import (
"os"
"path/filepath"
"github.com/Unknwon/com"
"github.com/go-martini/martini"
"github.com/gogits/gogs/modules/base"
"github.com/gogits/gogs/modules/middleware"
)
func SingleDownload(ctx *middleware.Context, params martini.Params) {
// Get tree path
treename := params["_1"]
blob, err := ctx.Repo.Commit.GetBlobByPath(treename)
if err != nil {
ctx.Handle(404, "repo.SingleDownload(GetBlobByPath)", err)
return
}
data, err := blob.Data()
if err != nil {
ctx.Handle(404, "repo.SingleDownload(Data)", err)
return
}
contentType, isTextFile := base.IsTextFile(data)
_, isImageFile := base.IsImageFile(data)
ctx.Res.Header().Set("Content-Type", contentType)
if !isTextFile && !isImageFile {
ctx.Res.Header().Set("Content-Disposition", "attachment; filename="+filepath.Base(treename))
ctx.Res.Header().Set("Content-Transfer-Encoding", "binary")
}
ctx.Res.Write(data)
}
func ZipDownload(ctx *middleware.Context, params martini.Params) {
commitId := ctx.Repo.CommitId
archivesPath := filepath.Join(ctx.Repo.GitRepo.Path, "archives")
if !com.IsDir(archivesPath) {
if err := os.Mkdir(archivesPath, 0755); err != nil {
ctx.Handle(404, "ZipDownload -> os.Mkdir(archivesPath)", err)
return
}
}
zipPath := filepath.Join(archivesPath, commitId+".zip")
if com.IsFile(zipPath) {
ctx.ServeFile(zipPath, ctx.Repo.Repository.Name+".zip")
return
}
err := ctx.Repo.Commit.CreateArchive(zipPath)
if err != nil {
ctx.Handle(404, "ZipDownload -> CreateArchive "+zipPath, err)
return
}
ctx.ServeFile(zipPath, ctx.Repo.Repository.Name+".zip")
}

View File

@ -145,7 +145,7 @@ func Single(ctx *middleware.Context, params martini.Params) {
return return
} }
if entry != nil && entry.IsFile() { if entry != nil && !entry.IsDir() {
blob := entry.Blob() blob := entry.Blob()
if data, err := blob.Data(); err != nil { if data, err := blob.Data(); err != nil {
@ -154,7 +154,7 @@ func Single(ctx *middleware.Context, params martini.Params) {
ctx.Data["FileSize"] = blob.Size() ctx.Data["FileSize"] = blob.Size()
ctx.Data["IsFile"] = true ctx.Data["IsFile"] = true
ctx.Data["FileName"] = blob.Name ctx.Data["FileName"] = blob.Name
ext := path.Ext(blob.Name) ext := path.Ext(blob.Name())
if len(ext) > 0 { if len(ext) > 0 {
ext = ext[1:] ext = ext[1:]
} }
@ -168,7 +168,7 @@ func Single(ctx *middleware.Context, params martini.Params) {
if isImageFile { if isImageFile {
ctx.Data["IsImageFile"] = true ctx.Data["IsImageFile"] = true
} else { } else {
readmeExist := base.IsMarkdownFile(blob.Name) || base.IsReadmeFile(blob.Name) readmeExist := base.IsMarkdownFile(blob.Name()) || base.IsReadmeFile(blob.Name())
ctx.Data["ReadmeExist"] = readmeExist ctx.Data["ReadmeExist"] = readmeExist
if readmeExist { if readmeExist {
ctx.Data["FileContent"] = string(base.RenderMarkdown(data, "")) ctx.Data["FileContent"] = string(base.RenderMarkdown(data, ""))
@ -193,7 +193,7 @@ func Single(ctx *middleware.Context, params martini.Params) {
files := make([][]interface{}, 0, len(entries)) files := make([][]interface{}, 0, len(entries))
for _, te := range entries { for _, te := range entries {
c, err := ctx.Repo.Commit.GetCommitOfRelPath(filepath.Join(treePath, te.Name)) c, err := ctx.Repo.Commit.GetCommitOfRelPath(filepath.Join(treePath, te.Name()))
if err != nil { if err != nil {
ctx.Handle(404, "repo.Single(SubTree)", err) ctx.Handle(404, "repo.Single(SubTree)", err)
return return
@ -207,7 +207,7 @@ func Single(ctx *middleware.Context, params martini.Params) {
var readmeFile *git.Blob var readmeFile *git.Blob
for _, f := range entries { for _, f := range entries {
if !f.IsFile() || !base.IsReadmeFile(f.Name) { if f.IsDir() || !base.IsReadmeFile(f.Name()) {
continue continue
} else { } else {
readmeFile = f.Blob() readmeFile = f.Blob()
@ -260,32 +260,6 @@ func Single(ctx *middleware.Context, params martini.Params) {
ctx.HTML(200, "repo/single") ctx.HTML(200, "repo/single")
} }
func SingleDownload(ctx *middleware.Context, params martini.Params) {
// Get tree path
treename := params["_1"]
blob, err := ctx.Repo.Commit.GetBlobByPath(treename)
if err != nil {
ctx.Handle(404, "repo.SingleDownload(GetBlobByPath)", err)
return
}
data, err := blob.Data()
if err != nil {
ctx.Handle(404, "repo.SingleDownload(Data)", err)
return
}
contentType, isTextFile := base.IsTextFile(data)
_, isImageFile := base.IsImageFile(data)
ctx.Res.Header().Set("Content-Type", contentType)
if !isTextFile && !isImageFile {
ctx.Res.Header().Set("Content-Disposition", "attachment; filename="+filepath.Base(treename))
ctx.Res.Header().Set("Content-Transfer-Encoding", "binary")
}
ctx.Res.Write(data)
}
func basicEncode(username, password string) string { func basicEncode(username, password string) string {
auth := username + ":" + password auth := username + ":" + password
return base64.StdEncoding.EncodeToString([]byte(auth)) return base64.StdEncoding.EncodeToString([]byte(auth))

1
web.go
View File

@ -176,6 +176,7 @@ func runWeb(*cli.Context) {
r.Get("/commit/:branchname", repo.Diff) r.Get("/commit/:branchname", repo.Diff)
r.Get("/commit/:branchname/**", repo.Diff) r.Get("/commit/:branchname/**", repo.Diff)
r.Get("/releases", repo.Releases) r.Get("/releases", repo.Releases)
r.Get("/archive/:branchname/:reponame.zip", repo.ZipDownload)
}, ignSignIn, middleware.RepoAssignment(true, true)) }, ignSignIn, middleware.RepoAssignment(true, true))
m.Group("/:username", func(r martini.Router) { m.Group("/:username", func(r martini.Router) {