一、需求

A(客户端)---------------》B(服务端)--------------》C(文件服务器)

在客户端需要显示图片列表,但是不想C(文件服务器)的地址被暴露出来,所以现在是A(客户端)发送URL到B(服务器),B(服务器)去请求C(文件服务器)的图片返回数据,B(服务器)返回图片到A(客户端)显示

注:B和C部署在不同的服务器

二、方法

1.如果C(文件服务器)是和B(服务端)部署在同一服务器,可以通过os.Open(filename string)(file *File,err error)直接将图片输出;

2.如果C(文件服务器)不是和B(服务端)部署在同一服务器,可以通过获取图片的数据经过base64后转化将数据输出到客户端;

3.如果C(文件服务器)不是和B(服务端)部署在同一服务器,通过B(服务端)获取C(文件服务器)的图片数据,直接将图片返回给客户端(下面实现

三、实现方法3

1.如何将图片可以直接输出到客户端,可根据os.Open(filename string)(file *File,err error)方法来实现返回http.File接口类型即可;

2.查看golang标准库可知道http.File类型接口的实现(net/http)

type File interface {
io.Closer
io.Reader
Readdir(count int) ([]os.FileInfo, error)
Seek(offset int64, whence int) (int64, error)
Stat() (os.FileInfo, error)
}

3.通过看http.File接口的方法返回值还需要去实现os.FileInfo类型的接口(查看文档os)

type FileInfo interface {
Name() string // 文件的名字(不含扩展名)
Size() int64 // 普通文件返回值表示其大小;其他文件的返回值含义各系统不同
Mode() FileMode // 文件的模式位
ModTime() time.Time // 文件的修改时间
IsDir() bool // 等价于Mode().IsDir()
Sys() interface{} // 底层数据来源(可以返回nil)
}

4.只要实现了http.File和os.FileInfo两个接口就可以返回能够输出到客户端的类型,实现以下方法

func Close() (err error) 

func Read(p []byte) (n int, err error) 

func Readdir(count int) ([]os.FileInfo, error) 

func Seek(offset int64, whence int) (int64, error) 

func Stat() (os.FileInfo, error)

func Name() string 

func Size() int64 

func Mode() os.FileMode 

func ModTime() time.Time 

func IsDir() bool 

func Sys() interface{} 

四、代码实现

package main

import (
"bytes"
"fmt"
"io/ioutil"
"net/http"
"os"
"path/filepath"
"time"
) //实现File和FileInfo接口的类
type ReadImg struct {
buf *bytes.Reader
fileUrl string
fileData []byte
} //获取C的图片数据
func ReadImgData(url string) []byte {
resp, err := http.Get(url)
if err != nil {
panic(err)
}
defer resp.Body.Close()
pix, err := ioutil.ReadAll(resp.Body)
if err != nil {
panic(err)
}
return pix
} //实现File和FileInfo接口
func (r *ReadImg) Close() (err error) {
return nil
} func (r *ReadImg) Read(p []byte) (n int, err error) {
return r.buf.Read(p)
} func (r *ReadImg) Readdir(count int) ([]os.FileInfo, error) {
var i os.FileInfo = &ReadImg{buf: bytes.NewReader(r.fileData), fileUrl: r.fileUrl, fileData: r.fileData}
return []os.FileInfo{i}, nil
} func (r *ReadImg) Seek(offset int64, whence int) (int64, error) {
return r.buf.Seek(offset, whence)
} func (r *ReadImg) Stat() (os.FileInfo, error) {
var i os.FileInfo = &ReadImg{buf: bytes.NewReader(r.fileData), fileUrl: r.fileUrl, fileData: r.fileData}
return i, nil
} func (r *ReadImg) Name() string {
return filepath.Base(r.fileUrl)[:len(filepath.Base(r.fileUrl))-4]
} func (r *ReadImg) Size() int64 {
return (int64)(len(r.fileData))
} func (r *ReadImg) Mode() os.FileMode {
return os.ModeSetuid
} func (r *ReadImg) ModTime() time.Time {
return time.Now()
} func (r *ReadImg) IsDir() bool {
return false
} func (r *ReadImg) Sys() interface{} {
return nil
} //处理请求
type HttpDealImg struct{} func (self HttpDealImg) Open(name string) (http.File, error) {
img_name := name[1:]
fmt.Println(img_name)
img_url := "http://localhost:8001/images/Test" + name //C(文件服务器地址)
img_data := ReadImgData(img_url) //向服务器气球图片数据
if len(img_data) == 0 {
fmt.Println("file access forbidden:", name)
return nil, os.ErrNotExist
}
fmt.Println("get img file:", img_url)
var f http.File = &ReadImg{buf: bytes.NewReader(img_data), fileUrl: img_name, fileData: img_data} //标红的可以查看标准库bytes的Reader类型,NewReader(p []byte)可返回*Reader,然后调用和http.File相同的Seek()和Read()方法
return f, nil
} func InitHttpImgFileServ() {
http.Handle("/img/", http.StripPrefix("/img/", http.FileServer(HttpDealImg{})))
} func main() {
InitHttpImgFileServ()
http.ListenAndServe(":8000", nil)
}

六、测试截图

请求地址http://localhost:8000/img/qq.png

后台打印的信息是获取的是http://localhost:8001/images/Test/qq.png,也就是C(文件服务器里图片的真实地址)

七、结束

当文件保存在其他的服务器上,需要在客户端显示图片,但是不想被知道真实的路径的时候就可以通过http.File和os.FileInfo去封装一下就可以实现,可能上面介绍的不清楚,有问题的可以留言一起沟通学习一下,谢谢!

如果有更好的实现方法,希望大家可以分享出来一起学习,谢谢、

Golang从文件服务器获取图片显示到客户端的更多相关文章

  1. Android相机、相册获取图片显示并保存到SD卡

    Android相机.相册获取图片显示并保存到SD卡 [复制链接]   电梯直达 楼主    发表于 2013-3-13 19:51:43 | 只看该作者 |只看大图  本帖最后由 happy小妖同学 ...

  2. 从网络中获取图片显示到Image控件并保存到磁盘

    一.从网络中获取图片信息: /// <summary> /// 获取图片 /// </summary> /// <param name="url"&g ...

  3. 根据url路径获取图片并显示到ListView中

    项目开发中我们需要从网络获取图片显示到控件中,很多开源框架如Picasso可以实现图片下载和缓存功能.这里介绍的是一种简易的网络图片获取方式并把它显示到ListView中. 本案例实现的效果如下: 项 ...

  4. Android ListView从网络获取图片及文字显示

    上一篇文章说的是ListView展示本地的图片以及文本,这一篇说一下如何从网络获取图片以及文本来显示.事实上,一般是先获取Josn或sml数据,然后解释显示.我们先从网上获取xml,然后对其进行解析, ...

  5. iOS 七牛云上传并获取图片----【客户端】

           最近做了七牛云存储的有关内容,涉及到与后台交互获取验证的token,无奈,后台自命清高,不与理会,没办法呀,于是自己搞呗.首先呢在在七牛上注册一个账号,然后呢添加一个存储空间这时候空间名 ...

  6. ios 从网络上获取图片并在UIImageView中显示

    ios 从网络上获取图片   -(UIImage *) getImageFromURL:(NSString *)fileURL { NSLog(@"执行图片下载函数"); UIIm ...

  7. Android从服务端获取json解析显示在客户端上面

    Android从服务端获取json解析显示在客户端上面 百度经验:jingyan.baidu.com 首先说一下Json数据的最基本的特点,Json数据是一系列的键值对的集合,和XML数据来比,Jso ...

  8. 获取Assets目录下的图片显示并上传

    package com.jingle.getlocal; import java.io.ByteArrayOutputStream; import java.io.InputStream; impor ...

  9. ajax 获取 mysql 保存的图片显示

    function ajax_GetFirstData(data) { var len = data.Data.length; if (len > 0) { $("#jquery_jpl ...

随机推荐

  1. twemproxy源码分析

    twemproxy是twitter开源的redis/memcached 代理,数据分片提供取模,一致性哈希等手段,维护和后端server的长连接,自动踢除server,恢复server,提供专门的状态 ...

  2. scrapy实战--登陆人人网爬取个人信息

    今天把scrapy的文档研究了一下,感觉有点手痒,就写点东西留点念想吧,也做为备忘录.随意写写,看到的朋友觉得不好,不要喷我哈. 创建scrapy工程 cd C:\Spider_dev\app\scr ...

  3. etcd 分布式数据库概念初探

    Lease(租约): 其实就是一个定时器.首先申请一个TTL=N的lease(定时器),然后创建key的时候传入该lease,那么就实现了一个定时的key. 在程序中可以定时为该lease续约,也就是 ...

  4. 转: 根据屏幕分辨率,浏览器调用不同css

    <link type="text/csss" href="" rel="stylesheet"/> <link type= ...

  5. python基础_类型_str

    #python不用考虑变量,可随时变换,自动分配内存,比如a = 'jjj'后a = 123是可以的 #str 文本 字符串 #常用函数 a = ' abcefg \n' a.strip() #去掉前 ...

  6. php常用算法和数据结构

    </pre><pre name="code" class="php"><?php /** * Created by PhpStor ...

  7. 【转】.NET Core基于. csproj 配置文件发布项目

    一.前言 .NET工具链在最新的Preview3版本中,引入了新的MSBuild项目系统,项目文件又回归了.csproj的XML文件来管理,项目文件.包引用.程序集引用..NET Core工具集.发布 ...

  8. Jenkins 配合 GitLab 实现分支的自动合并、自动创建 Tag

    Jenkins 配合 GitLab 实现分支的自动合并.自动创建 Tag 背景 GitFlow工作流简介 Gitflow工作流定义了一个围绕项目发布的严格分支模型,它会相对复杂一点,但提供了用于一个健 ...

  9. 【转载】Java 集合框架

    http://wangkuiwu.github.io/2012/02/03/collection-03-arraylist/ 网上比较全的Java集合框架教程. 注:transient是Java语言的 ...

  10. 使用python来搞定redis的订阅功能

    好久没写博客了.   最近公司开了新项目,我负责的内容之一是系统的后端.具体项目内容我就不介绍了,但是用到的技术有些还是很有趣的,值得记录一下.今天介绍的就是其中一个:利用redis的pubsub订阅 ...