首页 > 其他分享 >golang 实现文件下载

golang 实现文件下载

时间:2024-04-24 19:56:03浏览次数:26  
标签:files 文件 return err fileName golang Error http 下载

golang 实现文件下载

package main

import (
    "fmt"
    "html/template"
    "io"
    "io/fs"
    "mime"
    "net/http"
    "os"
    "path/filepath"
    "regexp"
    "strconv"
)

func getFiles(dir string) ([]string, error) {
    var files []string

    err := filepath.WalkDir(dir, func(path string, d fs.DirEntry, err error) error {
        if err != nil {
            return err
        }

        if !d.IsDir() {
            files = append(files, path)
        }

        return nil
    })

    return files, err
}

type FileInfo struct {
    Name string
    URL  string
}

var fileListTemplate = template.Must(template.New("fileList").Parse(`
    <html>
        <head><title>Available Files</title></head>
        <body>
            <h1>Available Files</h1>
            <ul>
                {{range .}}
                    <li><a href="{{.URL}}">{{.Name}}</a></li>
                {{end}}
            </ul>
        </body>
    </html>
`))

func listFilesHandler(w http.ResponseWriter, r *http.Request) {
    files, err := getFiles("G:\\Databackup") // 假设文件存储在项目根目录下的"files"目录
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    var fileInfos []FileInfo
    for _, filePath := range files {
        fileName := filepath.Base(filePath)
        fileInfos = append(fileInfos, FileInfo{Name: fileName, URL: "/" + fileName})
    }

    fileListTemplate.Execute(w, fileInfos)
}

func downloadFileHandler(w http.ResponseWriter, r *http.Request) {
    // 获取请求中的文件名
    fileName := r.URL.Path[1:] // 去掉前导斜杠

    // 安全检查:确保文件名仅包含合法字符,避免路径穿越攻击
    if !isValidFileName(fileName) {
        http.Error(w, "Invalid file name", http.StatusForbidden)
        return
    }

    // 构建完整文件路径
    filePath := "G:\\Databackup" + fileName

    // 打开文件并设置响应头
    file, err := os.Open(filePath)
    if err != nil {
        http.Error(w, err.Error(), http.StatusNotFound)
        return
    }
    defer file.Close()

    fileInfo, err := file.Stat()
    if err != nil {
        http.Error(w, err.Error(), http.StatusInternalServerError)
        return
    }

    contentType := mime.TypeByExtension(filepath.Ext(fileName))
    if contentType == "" {
        contentType = "application/octet-stream" // 默认未知类型为二进制流
    }

    w.Header().Set("Content-Type", contentType)
    w.Header().Set("Content-Disposition", fmt.Sprintf("attachment; filename=\"%s\"", fileName))
    w.Header().Set("Content-Length", strconv.FormatInt(fileInfo.Size(), 10))

    // 发送文件内容到客户端
    io.Copy(w, file)
}

func isValidFileName(name string) bool {
    // 实现一个简单的检查函数,仅允许字母、数字、下划线和点(用于扩展名)
    // 这里仅为示例,实际应用中可能需要更严格的过滤规则
    return regexp.MustCompile(`^[A-Za-z0-9._]+$`).MatchString(name)
}

func main() {
    http.HandleFunc("/", listFilesHandler)
    http.HandleFunc("/download", downloadFileHandler)

    port := ":8080" // 可以根据需要调整监听端口
    fmt.Printf("Listening on port %s for file listing and downloads.\n", port)
    err := http.ListenAndServe(port, nil)
    if err != nil {
        panic(err)
    }
}
View Code

 

标签:files,文件,return,err,fileName,golang,Error,http,下载
From: https://www.cnblogs.com/jason-zhao/p/18156194

相关文章

  • Markdown To blog 图片文件上传
    具体可见【博客园皮肤美化&写博客】https://www.bilibili.com/video/BV1Rv4y1Y7KH/?share_source=copy_web&vd_source=aa794a877150d12d2f1ff15d63616ad3安装配置打开运行窗口输入control找到程序和功能->启用或关闭windows功能安装NET3.5安装dotnet-sdk-5.0.408-......
  • 本地已经有项目需要的所有依赖,但是maven总是会去网上下载
    情况说明本地已经有项目需要的所有依赖,但是maven总是会去网上下载,因为网络不好等原因,一直下载失败,但是本地明明就已经有依赖了。maven的settings配置maven已经配置成自己下载的,至于仓库,没有改变路径,但是仓库的settings也改了。maven的settings已经配置成本地仓库:本地仓库的setti......
  • Linux统计文件内容重复行
    需求:在一个文件中,如下文件内容有许多乱序的重复值,那我们想要快速知道哪些是重复值怎么办?试问你能靠眼里10秒内找到吗?哈哈哈 解决方案:先使用sort命令将文件内容进行排序,再使用uniq命令进行统计重复值uniq常用参数-c#在每行前统计重复的次数......
  • 关于文件系统在创建目录文件和普通文件时的区别
    在上一篇探究linux解释器时同样涉及到了一些其他问题比如为什么在ls-lh时目录的大小都是4.0k? 之前想过可能是最小或者最大只能显示出4.0k的,但是就如上图显示的,这两种都是不可能的直到我在使用stat命令查看文件大小时忽然想到,用这个命令能不能查看文件夹的大小?然后发现还真......
  • 修改文件内容 python
    第一种方法,简单直接粗暴的,缺点就是如果文件非常大时,把所有内容都读出来,会非常占用内存:f=open('a.txt','a+',encoding='utf-8')#不能用w+,用w+直接给文件清空了,读不出来内容了f.seek(0)result=f.read()new_result=result.replace('abc','ABC')f.seek(0)f.truncate......
  • 新手下载python和anaconda3注意事项
    新手下载python和anaconda3要注意哪些1、python关于python下载其实很简单,直接在官网下载就行。官网:WelcometoPython.org当然,到了官网下载是默认最新版本,如果你需要旧版本,那就需要找一下了,这里提供一下windows的各版本的官网链接:PythonReleasesforWindows|Python.org......
  • linux命令从log文件中找出404 或者500的所有报错信息?
     你可以使用grep命令结合正则表达式来找出包含"404"或"500"的所有报错信息,并显示这些行的内容。以下是示例命令:grep-E'404|500'/path/to/logfile.log这个命令会在指定的日志文件/path/to/logfile.log中查找包含"404"或"500"的所有行,并将这些行显示出来。g......
  • 处理文件的小工具
    处理文件的小工具背景在实际工作中,我们经常需要处理一些文件,比如过滤一些log,找到一批文件中的特定数据等。为了提高工作效率以及灵活性,编写一个小工具来简化这些操作。主要针对程序员,自己可以动态调整方法,这里是一个框架,记录一下,省的以后用的时候找不到了。实现利用委托deleg......
  • 下载安装Gradle
    一、下载Gradle 1.Gradle官方下载地址:https://gradle.org/releases/  2.下载之后进行解压 二、配置环境变量 我的电脑->属性->高级系统设置->环境变量 在path里面添加:%GRADLE_HOME%\bin三、验证是否安装成功 打开CMD,输入gradle-v,此时会显示Gradle的版本......
  • ELF文件格式解析器 原理 + 代码
    参考:https://bbs.kanxue.com/thread-259901.htm写在前面:   读《Linux二进制》,发现作者对ELF文件格式部分并没有做详细介绍,为了加深对elf文件格式理解,我自己着手写了个解析器,会和readelf工具协同对比。 原理:  ELF文件(目标文件)格式主要三种:1.可重定向文件(Re......