HTTP实现xls导出和上传文件处理

时间: 2019-04-13阅读: 37标签: 文件

需求

  • 导出节目单[不保存文件到本地]
  • 输出不同的文件类型[csv,xls,xlsx]
  • 上传[csv,xls,xlsx]导入节目单


导出节目单

import (
    "bytes"
    "encoding/csv"
    "fmt"
    "net/http"
    "strings"

    "github.com/tealeg/xlsx"
)

//导出节目单的handler
func Export(w http.ResponseWriter, r *http.Request) {
    q := r.URL.Query()
    format := strings.ToLower(q.Get("format"))
    // 获取节目单
    ps := dbqueryprograms()

    // 设置文件头
    w.Header().Set("ContentType", "application/octet-stream")
    w.Header().Set("Content-Disposition", fmt.Sprintf("attachment;filename=节目单.%s", format))
    if format == "csv" {
        b := &bytes.Buffer{}
        wr := csv.NewWriter(b)
        wr.WriteString("\xEF\xBB\xBF")
        wr.Write([]string{"节目名称", "开始时间", "结束时间", "播出类型", "素材ID"})
        for _, p := range ps {
            wr.Write([]string{p.Name, p.StartTime, p.EndTime, p.Type, p.VideoId})
        }

        wr.Flush()
        w.Write(b.Bytes())
        return
    } else if format == "xls" || format == "xlsx" {
        file := xlsx.NewFile()
        sheet, err := file.AddSheet("sheet1")
        if err != nil {
            DoHttpError(w, "文件创建失败")
            return
        }

        title := &rowContent{"节目名称", "开始时间", "结束时间", "播出类型", "素材ID"}
        writeRow(sheet, title)

        for _, p := range ps {
            line := &rowContent{
                Name:        p.Name,
                Start:       p.StartTime,
                End:         p.EndTime,
                PlayingType: p.Type,
                VideoID:     p.VideoId,
            }
            writeRow(sheet, line)
        }
        // 直接输出到response
        file.Write(w)
        return
    }

    DoHttpError(w, "不支持的文件类型")
    return
}

func writeRow(sheet *xlsx.Sheet, c *rowContent) {
    row := sheet.AddRow()
    nameCell := row.AddCell()
    nameCell.Value = c.Name

    startCell := row.AddCell()
    startCell.Value = c.Start

    endCell := row.AddCell()
    endCell.Value = c.End

    typeCell := row.AddCell()
    typeCell.Value = c.PlayingType

    videoCell := row.AddCell()
    videoCell.Value = c.VideoID
}

type rowContent struct {
    Name, Start, End, PlayingType, VideoID string
}


文件上传

import (
    "encoding/csv"
    "io"
    "mime/multipart"
    "net/http"
    "path"
    "strings"

    "github.com/pkg/errors"
    "github.com/tealeg/xlsx"
)

func ImportHandler(w http.ResponseWriter, r *http.Request) {
    file, handler, err := r.FormFile("file")
    if err != nil {
        DoHttpError(w, "获取上传文件失败")
        return
    }
    defer file.Close()

    if handler.Size > 100*1024*1024 {
        DoHttpError(w, "上传不能超过100M")
        return
    }

    fileExt := strings.ToLower(path.Ext(handler.Filename))
    var content [][]string
    if fileExt == ".csv" {
        content, err = parseCsv(file)
        if err != nil {
            // handle err and log
            return
        }
    } else if fileExt == ".xls" || fileExt == ".xlsx" {
        content, err = parseXlsx(file, handler.Size)
        if err != nil {
            // handle err and log
            return
        }
    } else {
        DoHttpError(w, "不支持的类型")
        return
    }

    // db and handle err log
    // err := DbCreatePrograms(content)
    DoHttpSuccess(w, "解析成功", nil)
    return
}

// 解析csv文件
func parseCsv(file multipart.File) ([][]string, error) {
    result := [][]string{}
    r := csv.NewReader(file)
    for {
        record, err := r.Read()
        if err == io.EOF {
            break
        } else if err != nil {
            return nil, errors.Wrap(err, "Read csv failed")
        }

        var st = []string{}
        for i, j := range record {
            // 头信息过滤掉
            if i == 0 {
                continue
            }
            st = append(st, j)
        }
        result = append(result, st)
    }
    return result, nil
}

// 解析xlsx文件
func parseXlsx(file multipart.File, size int64) ([][]string, error) {
    result := [][]string{}
    xlFile, err := xlsx.OpenReaderAt(file, size)
    if err != nil {
        return nil, errors.Wrap(err, "Read file failed;")
    }

    for _, sheet := range xlFile.Sheets {
        // 不读隐藏的工作区
        if sheet.Hidden {
            continue
        }

        for i, row := range sheet.Rows {
            // 过滤头信息
            if i == 0 {
                continue
            }
            var st = []string{}
            for j, cell := range row.Cells {
                c, err := cell.FormattedValue()
                if err != nil {
                    return nil, errors.Wrapf(err, "Get (%v, %v) value failed;", i, j)
                }
                st = append(st, c)
            }
            result = append(result, st)
        }
    }
    return result, nil
}

前端实现文件在线预览txt,pdf,doc,xls,ppt几种格式

做法就是使用iframe标签,只需要配置src就可以,根据文件后缀判断如果是office的类型就在url前加上https://view.officeapps.live.com/op/view.aspx?src=

前端文件下载的方式

http 头部的 Content-Disposition字段,规定了返回的内容用什么形式展示,前端需要使用window.open 形式访问 此路由就可以实现文件的下载

前端实现在线预览pdf、word、xls、ppt等文件

免费纯前端方式实现在线预览word、excel、ppt最优选择微软在线预览(不可编辑),利用后端将文件转为图片,前端以图片形式预览(可行方案)

将数组转化为 csv 文件类型的代码

将一个数组转化为逗号为分割符的字符串(CSV)即表格数据。利用了 Array.prototype.map() 和 Array.prototype.join() 两个函数,实现了一个简单的数组转化为 csv 文件类型的代码。

JavaScript使用localStorage缓存Js和css文件

对于WebApp来说,将js css文件缓存到localstorage区可以减少页面在加载时与HTTP请求的交互次数,从而优化页面的加载时间.特别是当移端信号不好高延迟时优化效果还是很显见的

php使用 header 头下载文件

header() 函数向客户端发送原始的 HTTP 报头。认识到一点很重要,即必须在任何实际的输出被发送之前调用 header() 函数

PHP遍历目录和文件及子目录和文件

正常直接使用opendir方法,就可以读到所有的目录和文件。文件可以直接记录下来,目录则需要再进一步获取里边的文件信息。也就是,如果当前读出来是目录,则需要再次调用函数本身(递归)

上传文件异常问题_413 Request Entity Too Large的解决方法

对于有经验的开发着看见这个错误第一反应就是服务器的上传大小设置的不对那么修改服务器上传大小。对于nginx的配置有三个地方可以设置.解决413的正常途径.分别是 http,server,location 根据实际情况设置具体的大小

js实现带上传进度的文件上传

获取文件筐的文件集合,创建FormData对象 相当于参数集合 存储方式是键值对,添加第一个文件到FormData,添加普通数据 后台直接参数接受,创建异步对象

php实现rar文件的读取和解压

PHP Rar Archiving 模块 (php_rar) 是一个读取和解压rar文件的模块,但不提供RAR压缩(打包)的功能。首先要到PECL的RAR页面下载DLL. 根据自己的情况选择下载对应版本的DLL.

内容以共享、参考为目的,请勿用于商业用途。其版权归原作者所有,如有侵权,请与小编联系,情况属实将予以删除!

广告赞助文章投稿关于web前端网站点搜索站长推荐网站地图站长QQ:522607023

小程序专栏: 土味情话心理测试脑筋急转弯幽默笑话段子句子语录成语大全