一、需求

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. 带你从零学ReactNative开发跨平台App开发(十)

    ReactNative跨平台开发系列教程: 带你从零学ReactNative开发跨平台App开发(一) 带你从零学ReactNative开发跨平台App开发(二) 带你从零学ReactNative开发 ...

  2. JVM知识(一):基础原理

    学过java知识和技术人,都应该听说过jvm,jvm一直是java知识里面晋级阶段的重要部分,如果想要在java技术领域更深入一步,jvm是必须需要明白的知识点. 本篇来讲解jvm的基础原理,先来熟悉 ...

  3. 由delete导致的超时已过期问题

    1. 问题 开发人员反映应用程序中一条简单的delete语句执行报“超时已过期”错误.delete语句形式如下: delete * from table_1 where id=@value 2. 分析 ...

  4. iostat 工具分析I/O性能

    iostat命令用途:主要用于监控系统设备的IO负载情况,iostat首次运行时显示自系统启动开始的各项统计信息,之后运行iostat将显示自上次运行该命令以后的统计信息.用户可以通过指定统计的次数和 ...

  5. 使用 PowerShell 创建和修改 ExpressRoute 线路

    开始之前 安装最新版本的 Azure Resource Manager PowerShell cmdlet. 有关详细信息,请参阅 Azure PowerShell 概述. 在开始配置之前,请查看先决 ...

  6. jetty8 中的异常 There is an error in invoking javac. A full JDK (not just JRE) is required...

    在jetty文件夹下的start.ini文件里有这么一行"-Dorg.apache.jasper.compiler.disablejsr199=true"注释,把这个注释去掉,再启 ...

  7. HTML--<frameset>標簽

    <html><frameset rows="20,80"> <frame src="/example/html/frame_a.html&q ...

  8. 关于jquery的serialize方法转换空格为+号的解决方法

    jquery的 serialize()方法,可以对表单项进行序列化,这本来是很方便的一个功能:但是实际使用中去发现了如下问题:例如:< textarea name="content&q ...

  9. CSS学习摘要-语法和选择器

    主要摘自网络开发者. 从最基本的层次来看,CSS是由两块内容组合而成的: 属性(Property):一些人类可理解的标识符,这些标识符指出你想修改哪一些样式,例如:字体,宽度,背景颜色等. 属性值(V ...

  10. 三星平板SM-T320刷机

    三星 Galaxy Tab Pro 8.4 (SM-T320) / 国行 固件下载 刷机教程 下载手机驱动,刷机工具Odin,相应的固件包,手机和电脑用数据线连接安装好手机的驱动. 手机先完全的关机, ...