主调函数,设置路由表

package main

import (
"fmt"
"net/http"
"store/handler"
) func main() {
http.HandleFunc("/file/upload", handler.UploadHandler)
http.HandleFunc("/file/upload/suc", handler.UploadSucHandler)
http.HandleFunc("/file/meta", handler.GetFileMetaHandler)
http.HandleFunc("/file/download", handler.DownloadHandler)
http.HandleFunc("/file/delete", handler.FileDelHandler)
http.HandleFunc("/file/update", handler.FileMetaUpdateHandler)
err := http.ListenAndServe(":8080", nil)
if err != nil {
fmt.Printf("Failed to start server: %s", err.Error())
}
}

文件元信息

package meta

// FileMeta 文件元信息结构
type FileMeta struct {
FileSha1 string // 文件哈希
FileName string // 文件名
FileSize int64 // 文件大小
Location string // 文件位置
UploadAt string // 上传时间
} // 保存文件元信息映射
var fileMetas map[string]FileMeta func init() {
fileMetas = make(map[string]FileMeta) // 初始化
} // UpdateFileMeta 更新文件元信息
func UpdateFileMeta(fileMeta FileMeta) {
fileMetas[fileMeta.FileSha1] = fileMeta
} // GetFileMeta 获取文件元信息对象
func GetFileMeta(fileSha1 string) FileMeta {
return fileMetas[fileSha1]
} // RemoveFileMeta 删除文件元信息
func RemoveFileMeta(fileSha1 string) {
delete(fileMetas, fileSha1)
}

handler逻辑

package handler

import (
"encoding/json"
"io"
"io/ioutil"
"log"
"net/http"
"os"
"store/meta"
"store/utils"
"time"
) const storePath = "./tmp/" func UploadHandler(w http.ResponseWriter, r *http.Request) {
if r.Method == "GET" {
// HTML 上传页面
data, err := ioutil.ReadFile("./static/view/index.html")
if err != nil {
_, _ = io.WriteString(w, "internal server error")
return
}
_, _ = io.WriteString(w, string(data))
} else if r.Method == "POST" {
// 接收文件流
file, head, err := r.FormFile("file")
if err != nil {
log.Printf("Failed to get data: %s\n", err.Error())
_, _ = io.WriteString(w, "")
return
}
defer file.Close() fileMeta := meta.FileMeta{
FileName: head.Filename,
Location: storePath + head.Filename,
UploadAt: time.Now().Format("2006-01-02 15:04:05"),
} newFile, err := os.Create(fileMeta.Location)
if err != nil {
log.Printf("Failed to create file: %s\n", err.Error())
return
}
defer newFile.Close()
_, err = io.Copy(newFile, file)
if err != nil {
log.Printf("Failed to save data into file: %s\n", err.Error())
return
} _, _ = newFile.Seek(0, 0)
fileMeta.FileSha1 = utils.FileSha1(newFile)
meta.UpdateFileMeta(fileMeta) http.Redirect(w, r, "/file/upload/suc", http.StatusFound)
}
} func UploadSucHandler(w http.ResponseWriter, r *http.Request) {
_, _ = io.WriteString(w, "Upload successfully")
} // GetFileMetaHandler 获取文件元信息
func GetFileMetaHandler(w http.ResponseWriter, r *http.Request) {
_ = r.ParseForm()
fileHash := r.Form["filehash"][0]
fileMeta := meta.GetFileMeta(fileHash)
data, err := json.Marshal(fileMeta)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
_, _ = w.Write(data)
} func DownloadHandler(w http.ResponseWriter, r *http.Request) {
_ = r.ParseForm()
fileHash := r.Form.Get("filehash")
fileMeta := meta.GetFileMeta(fileHash)
file, err := os.Open(fileMeta.Location)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
defer file.Close()
data, err := ioutil.ReadAll(file)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
} w.Header().Set("Content-Type", "application/octet-stream")
w.Header().Set("Content-Disposition", "attachment;filename=\""+fileMeta.FileName+"\"")
_, _ = w.Write(data)
} func FileDelHandler(w http.ResponseWriter, r *http.Request) {
_ = r.ParseForm()
fileHash := r.Form.Get("fileHash")
fileMeta := meta.GetFileMeta(fileHash)
_ = os.Remove(fileMeta.Location)
meta.RemoveFileMeta(fileHash)
w.WriteHeader(http.StatusOK)
} func FileMetaUpdateHandler(w http.ResponseWriter, r *http.Request) {
if r.Method != "POST" {
w.WriteHeader(http.StatusMethodNotAllowed)
return
} _ = r.ParseForm()
opType := r.Form.Get("op")
if opType != "0" {
w.WriteHeader(http.StatusForbidden)
return
} fileHash := r.Form.Get("filehash")
newFileName := r.Form.Get("filename")
curFileMeta := meta.GetFileMeta(fileHash)
curFileMeta.FileName = newFileName
meta.UpdateFileMeta(curFileMeta) data, err := json.Marshal(curFileMeta)
if err != nil {
w.WriteHeader(http.StatusInternalServerError)
return
}
w.WriteHeader(http.StatusOK)
_, _ = w.Write(data)
}

加密

package utils

import (
"crypto/md5"
"crypto/sha1"
"encoding/hex"
"hash"
"io"
"os"
"path/filepath"
) type Sha1Stream struct {
_sha1 hash.Hash
} func (obj *Sha1Stream) Update(data []byte) {
if obj._sha1 == nil {
obj._sha1 = sha1.New()
}
obj._sha1.Write(data)
} func (obj *Sha1Stream) Sum() string {
return hex.EncodeToString(obj._sha1.Sum([]byte("")))
} func Sha1(data []byte) string {
_sha1 := sha1.New()
_sha1.Write(data)
return hex.EncodeToString(_sha1.Sum([]byte("")))
} func FileSha1(file *os.File) string {
_sha1 := sha1.New()
_, _ = io.Copy(_sha1, file)
return hex.EncodeToString(_sha1.Sum(nil))
} func MD5(data []byte) string {
_md5 := md5.New()
_md5.Write(data)
return hex.EncodeToString(_md5.Sum([]byte("")))
} func FileMD5(file *os.File) string {
_md5 := md5.New()
_, _ = io.Copy(_md5, file)
return hex.EncodeToString(_md5.Sum(nil))
} func PathExists(path string) (bool, error) {
_, err := os.Stat(path)
if err == nil {
return true, nil
}
if os.IsNotExist(err) {
return false, nil
}
return false, err
} func GetFileSize(filename string) int64 {
var result int64
_ = filepath.Walk(filename, func(path string, f os.FileInfo, err error) error {
result = f.Size()
return nil
})
return result
}

前端:

<html lang="">

<head>
<!-- bootstrap 4.x is supported. You can also use the bootstrap css 3.3.x versions -->
<link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/css/bootstrap.min.css">
<link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-fileinput/4.4.9/css/fileinput.min.css" media="all"
rel="stylesheet" type="text/css" />
<!-- if using RTL (Right-To-Left) orientation, load the RTL CSS file after fileinput.css by uncommenting below -->
<!-- link href="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-fileinput/4.4.9/css/fileinput-rtl.min.css" media="all" rel="stylesheet" type="text/css" /-->
<script src="https://code.jquery.com/jquery-3.2.1.min.js"></script>
<!-- piexif.min.js is needed for auto orienting image files OR when restoring exif data in resized images and when you
wish to resize images before upload. This must be loaded before fileinput.min.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-fileinput/4.4.9/js/plugins/piexif.min.js"
type="text/javascript"></script>
<!-- sortable.min.js is only needed if you wish to sort / rearrange files in initial preview.
This must be loaded before fileinput.min.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-fileinput/4.4.9/js/plugins/sortable.min.js"
type="text/javascript"></script>
<!-- purify.min.js is only needed if you wish to purify HTML content in your preview for
HTML files. This must be loaded before fileinput.min.js -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-fileinput/4.4.9/js/plugins/purify.min.js"
type="text/javascript"></script>
<!-- popper.min.js below is needed if you use bootstrap 4.x. You can also use the bootstrap js
3.3.x versions without popper.min.js. -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.11.0/umd/popper.min.js"></script>
<!-- bootstrap.min.js below is needed if you wish to zoom and preview file content in a detail modal
dialog. bootstrap 4.x is supported. You can also use the bootstrap js 3.3.x versions. -->
<script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.0.0-beta/js/bootstrap.min.js"
type="text/javascript"></script>
<!-- the main fileinput plugin file -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-fileinput/4.4.9/js/fileinput.min.js"></script>
<!-- optionally if you need a theme like font awesome theme you can include it as mentioned below -->
<script src="https://cdnjs.cloudflare.com/ajax/libs/bootstrap-fileinput/4.4.9/themes/fa/theme.js"></script>
<!-- optionally if you need translation for your language then include locale file as mentioned below -->
<title></title>
</head> <body style="width:100%;height:100%;text-align:center;">
<div style="width:60%;height:30%;text-align:center;">
<form action='#' method="post" enctype="multipart/form-data">
<input id="file" name="file" type="file" class="file" data-msg-placeholder="选择文件">
</form>
</div>
</body> </html>

目录结构

.
├── go.mod
├── handler
│   └── handler.go
├── main.go
├── meta
│   └── file.go
├── static
│   └── view
│   ├── index.html
│   └── search.html
├── tmp
│   └── apple.jpg
└── utils
└── utils.go

Go语言实现文件服务器的更多相关文章

  1. JVM 平台上的各种语言的开发指南

    JVM 平台上的各种语言的开发指南 为什么我们需要如此多的JVM语言? 在2013年你可以有50中JVM语言的选择来用于你的下一个项目.尽管你可以说出一大打的名字,你会准备为你的下一个项目选择一种新的 ...

  2. Ueditor1.4.3实现跨域上传到独立文件服务器,完美解决单文件和多文件上传!

    再写配置方法之前先吐槽一下网上的各种教程,TM没一个有卵用,一群傻屌不会写就别写,写了就要负责. 百度google搜了半天,全是配置什么document.domain,根域名什么的,我只想对你说: 好 ...

  3. Java语言进阶过程(转)

    [以下肯定是不完整的列表,欢迎补充] Java是一个通用的编程语言,其实可以干很多事,怎么学Java就看怎么用了. 但有一些一般的步骤: 1. 熟悉一种文本编辑器,比如Vim, Emacs, Note ...

  4. 无敌简单快速的文件服务器sgfs

    前言 想要构建一个Linux文件服务器?看看下面几个要求是不是你想要的? 1.只需要单节点部署就够了 2.部署启动简单,下载之后,一键启动,一键关闭 3.不需要任何其他的依赖安装,而且运行时占用内存资 ...

  5. linux搭建FastDFS文件服务器

    本文主要介绍在linux服务器如何搭建FastDFS文件服务器.大概分为9个步骤,由于内容较为繁琐.下面带你入坑! 首先简单介绍一下FastDFS是淘宝资深架构师余庆老师主导开源的一个分布式文件系统, ...

  6. 不安分的 Go 语言开始入侵 Web 前端领域了!( WebAssembly )

    参考:https://blog.csdn.net/csdnnews/article/details/84038848 从 Go 语言诞生以来,它就开始不断侵蚀 Java .C.C++ 语言的领地.今年 ...

  7. 百度富文本编辑器整合fastdfs文件服务器上传

    技术:springboot+maven+ueditor   概述 百度富文本整合fastdfs文件服务器上传 详细 代码下载:http://www.demodashi.com/demo/15008.h ...

  8. 开源文件服务器file-service介绍

    file-service 一个基于ASP.NET Core的可伸缩.通用的文件服务器. 通常后端项目可能会有头像.图片.音频.视频等上传/下载需求,这些需求都可以抽象为文件服务. 功能特点 支持Lin ...

  9. Golang vs PHP 之文件服务器

    前面的话 作者为golang脑残粉,本篇内容可能会引起phper不适,请慎读! 前两天有同事遇到一个问题,需要一个能支持上传.下载功能的HTTP服务器做一个数据中心.我刚好弄过,于是答应帮他搭一个. ...

  10. Go语言编程 (许式伟 等 著)

    第1章 初识Go语言 1.1 语言简史 1.2 语言特性 1.2.1 自动垃圾回收 1.2.2 更丰富的内置类型 1.2.3 函数多返回值 1.2.4 错误处理 1.2.5 匿名函数和闭包 1.2.6 ...

随机推荐

  1. Hex格式和Mot格式简介

    Hex格式和Mot格式简介 一.Hex格式介绍    1.1 什么是 Intel HEX 文件格式?  Intel HEX文件 是由一行行符合 Intel HEX文件格式的文本所构成的ASCII文本文 ...

  2. 【前端样式】关于Element-plus 菜单 unique-opened不生效的问题

    需要保证el-sub-menu 的唯一性,即index得写在el-sub-menu上,否则 unique-opened 属性不生效.

  3. tensorflow2.0+TF-lite 各种报错

    generic_type: type "InterpreterWrapper" is already registered! 原因:tensorflow2.5.0rc0版本太高,降 ...

  4. 全新TI AM62xx系列核心板上市,小小身板蕴藏巨大势能!

    2011年TI推出AM335x,成为了此后市场上最受欢迎的通用工业级ARM处理器,并广泛应用于工业HMI, 医疗电子,机器人,能源,汽车等领域.随着工业4.0的发展,HMI人机交互.工业工控.医疗等领 ...

  5. [Unity工具]搭建lua环境(IDEA)

    一.下载IDEA 地址:https://www.jetbrains.com/idea/ 这里我的版本是IntelliJ IDEA Community Edition 2020.2.4 x64 二.断点 ...

  6. 后端004-JWT工具类的编写

    登录功能采用springsecurity安全框架和jwt令牌 首先需要添加依赖信息 在yml中添加JWT的配置文件 有了上述的配置之后,我们可以准备一个JWT的工具类,方便后面和JWT相关的内容去使用 ...

  7. Promise和await、同步和异步

    1.同步和异步是什么: ​ ①同步:同步是指如果一个进程在执行某个请求的时候,如果该请求需要等待一段时间,那么该进程会一直等待下去,直到收到返回信息才继续执行下去 ​ ②异步: 指一个请求在执行某个请 ...

  8. (2)请用requests库的get()函数访问如下一个网站20次,打印返回状态,text()内容,计算text()属性和content属性所返回网页内容的长度。

    # 导入库 import requests from bs4 import BeautifulSoup def getUrlText(url): try: web = requests.get(url ...

  9. 基于leaflet地图可视化(一)

    最近,在学习地图可视化是基于公司的项目.但公司在项目上居然用图片来代替.无语~~~项目效果图(第一版)如下: 突发奇想,2016年自己就接触过地图可视化.但那是没有深入研究.只会用R语言来实现点基础. ...

  10. vue树形结构图

    1.下载插件:cnpm i vue2-org-tree 2.下载less-loader不然报错(this.getOptions is not a function):npm install less- ...