一、需求

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. linux 获取shell内置命令帮助信息 help xx

    shell,命令解释器 shell内置命令有cd/umask/pwd等 help shell内置命令适用于所有用户获取shell内置命令的帮助信息help umaskhelp if

  2. redis介绍(2)简单安装

    我分两种方式讲解 window 下载地址:https://github.com/MSOpenTech/redis/releases. Redis 支持 32 位和 64 位.这个需要根据你系统平台的实 ...

  3. 分别用C/C++ 和 C#实现简单的观察者模式

    网上找了很多关于观察者模式的代码例子和文章,都写的比较复杂,我个人还是喜欢从易到难,今天自己参考网上资料,也写了一个简单观察者模式的例子,简单的复习了一下Observer 模式,Observer 模式 ...

  4. Entity Framework 更新模式之Attach与EntityState.Modified模式的区别

    数据库中有一个City表 初始时数据: 实体类与Fluent Api配置映射 public class City { public int Id { get; set; } public string ...

  5. 如何通过rman的增量备份恢复dataguard中standby端的数据

    很多正在使用dataguard的客户,都会遇到一个棘手的问题: 在备份端与主库同步的过程中由于网络原因或磁盘问题导致一个或多个归档日志丢失,进而dataguard同步无法继续.很多客户都选择了重新全库 ...

  6. [翻译] CRPixellatedView-用CIPixellate滤镜动态渲染UIView

    CRPixellatedView-用CIPixellate滤镜动态渲染UIView https://github.com/chroman/CRPixellatedView 本人测试的效果: Usage ...

  7. 铁乐学python_Day39_多进程和multiprocess模块2

    铁乐学python_Day39_多进程和multiprocess模块2 锁 -- multiprocess.Lock (进程同步) 之前我们千方百计实现了程序的异步,让多个任务可以同时在几个进程中并发 ...

  8. c++与matlab联合编程,调用Deploytool 生成exe文件和dll文件(转)

    转自:http://www.cnblogs.com/xlw1219/archive/2012/12/25/2832222.html 首先必须知道联合编程需要知道的一些命令解释: mcc 的作用是将 . ...

  9. Python成员运算符

    Python成员运算符 其他语言没有,是否包含运算符,主要应用在字符串或者集合中 测试实例中包含了一系列的成员,包括字符串,列表或元组. #使用场景01:字符串是否包含另外一个字符串? str01 = ...

  10. ZT 安卓手机的安全性 prepare for Q

    如何增强安卓手机的安全性?安卓的安全性太低了!!! 众所周知,安卓手机是非常容易破解的,刷过机的人都知道,不管你之前在手机怎么设置密码,只要进入recovery清空使用记录,手机就会恢复出厂设置,到时 ...