Ext.BLANK_IMAGE_URL

相信各位读者在学习Ext官方示例的时候,会发现每个例子都会引用examples.js。examples.js文件中的第一句就是:

Ext.BLANK_IMAGE_URL = '../../resources/images/default/s.gif';

这是一句将图片地址赋给Ext.BLANK_IMAGE_URL变量的语句。单单看这句话看不出有什么特殊,下面我们看Ext源代码GridView.js中的语句,来学习Ext.BLANK_IMAGE_URL的真正含义。

JavaScript代码清单10-1-1

if (!ts.hcell) {

ts.hcell = new Ext.Template(

'<td class="x-grid3-hd x-grid3-cell x-grid3-td-{id}" style="{style}">'

+ '<div {tooltip} {attr} class="x-grid3-hd-inner x-grid3-hd-{id}"

unselectable="on" style="{istyle}">',

        //判断grid是否启用了菜单

        this.grid.enableHdMenu

        ? '<a class="x-grid3-hd-btn" href="#"></a>'

        : '',

     '{value}<img class="x-grid3-sort-icon" src="', Ext.BLANK_IMAGE_URL, '" />',

    "</div></td>");

}

这段代码是生成Grid的列标题,通过模板动态生成列标题的样式,并定义列标题的排序图标。通过章节开始的那句赋值语句我们就应该知道排序图片是指向‘../../resources/ images/default/s.gif’,s.gif是一个空白的图片,意思是列标题在没有进行排序的情况下默认不显示任何图片,通过运行Ext官方示例Editor Grid Example在FireFox下面查看最终源代码会更加清楚,如图10.1中的红框处所示。

图10.1  最终的源代码

那么可以说明,排序图标是需要动态创建的,在点击Grid的列标题进行排序的时候,Ext会动态地修改CSS来设置图片修饰组件<img>的src属性,来实现图片的动态加载。

这样可以看出,Ext在对一些需要应用图片的地方,都没有显式地写明要应用的图片路径,而都是通过CSS来动态配置,许多应用图片的地方刚开始都使用Ext.BLANK_IMAGE_URL来替代,而在CSS加载之后就会替换到真实的图片路径。另外Ext.BLANK_IMAGE_URL在Ext默认的值为:

BLANK_IMAGE_URL : "http:/"+"/extjs.com/s.gif"

这是连接官方Ext网站的图片,这样如果您的图片在网络不通的情况下会显示一个红叉,所以还是建议在实际应用中将Ext.BLANK_IMAGE_URL设置为本地引用。最后还经过实践证明,如果没有正确地配置Ext.BLANK_IMAGE_URL,可能在许多控件上显示不了CSS文件中定义的装饰图标。

Ext软件包下面的Resources文件夹放置了Ext所需的全部资源文件,包括样式表(css)、图片等,但唯一不包括的一张图片是像素1 * 1的透明GIF文件,为什么这张图片如此特别,需要另作处理呢?我们先从网页的背景图制作方法说起——这是在前端设计中一种非常有用的处理手段。

Ext样式精粹

一般情况下,在HTML页面中插入图片很简单,直接定义Img元素的src属性即可:

<img src="image.gif" />

<a href="http://foo.com"><img src="image.gif" /></a>

<!--套上link元素做连接-->

渐渐地,人们意识到这样更换样式的同时需要修改HTML文件(仅仅是修改img元素的引用地址),不如修改CSS文件方便,不会涉及HTML结构有影响小的特点,于是一个空白图片做占位符号,然后用CSS文件里配置的背景图片做显示,这样有利于更换主题。上面的代码变为HTML和CSS两种:

HTML:

<div id="image"></div>

CSS:

#image {

    height: 30px;

    width: 50px;

     background-image:url(../images/index.gif);

}

此时的div元素中的innerHTML属性为空,即不包含任何字符。问题出现这里了,我们不能直接给div元素套上link元素,否则不能建立连接或div出现异常,如这里给出的一个错误的用法,见源码10-1-1。

源码10-1-1 (错误的用法)

<style>

#image {

    height: 30px;

    width: 50px;

    background:blue;

}

</style>

<a href="#">

    <div id="image"></div>

</a>

<!--如果我想把两个元素“调过来”,div元素嵌套a元素也不行,因为a元素不支持height、width尺寸的属性-->

要可靠地为div元素加上连接,同时也希望利用CSS配置的背景图片,可以利用一种折中但有效的方法,在a元素中包含一个透明的GIF图片,该图片大小为1 * 1像素,IMG元素的尺寸大小就按照实际显示的大小设置。IMG此时的作用不是显示要显示的图片,而是让透明的图片不断地被填充,达到不影响背景图片而又设置大小尺寸的效果。

不过,此时我们距离真正解决问题还差一步之遥。因为这个IMG元素不能够以背景图(在CSS里面)的方式引用那个1 * 1的透明图片。IMG元素本来的用途是显示图片,再加入背景图岂不是多此一举,因此在W3C(HMTL标准制定者)的规范中,IMG元素是不存在背景图的属性或相关设置方法的。如此一来,我们便不能遵从CSS文件路径的定位标准去定义这个透明图片(CSS与HTML路径各自成独立体系),好在这只是唯一需要我们设置的地方,一次定义正确,整个Ext库都能引用这个图片路径。

 

CSS图片拼合(CSS sprites)可有效降低图片文件的HTTP连接请求数。多个图片将以一定间距合并为一个大图片文件。页面中使用这些图片的元素将利用background-position这一CSS属性来显示拼合图片中的指定位置。就好比手表上的日期,你今天看到的是21,明天看到的是22,是因为它的位置往上跳了一格。

总地来说,将几张图片合成一个大图,并给出CSS座标,这就是CSS Sprites的精粹所在,也是Ext制作皮肤的总体思路。

这一技术可有效提升网站的性能, 尤其是网页上有众多小图片时——如许多菜单栏图标。Yahoo!首页是使用此技术的一个实例。

class FilePreviewHandler(tornado.web.RequestHandler): async def get(self): pool_name = self.get_argument("pool") raw_file_name = self.get_argument("file") file_name = urllib.parse.unquote(raw_file_name) if pool_name not in RESOURCE_POOLS: self.set_status(404) self.render("404.html") return pool_path = RESOURCE_POOLS[pool_name]["path"] file_path = os.path.normpath(os.path.join(pool_path, file_name)) real_request_path = os.path.realpath(file_path) real_pool_path = os.path.realpath(pool_path) if not real_request_path.startswith(real_pool_path): self.set_status(403) self.write("禁止访问此文件路径") return if not os.path.exists(file_path): self.set_status(404) self.render("404.html") return ext = os.path.splitext(file_name)[1].lower() # 特别处理 PDF 文件:使用本地 PDF.js 预览 if ext == ".pdf": # 构造预览链接,不要双重编码 proxy_url = f"/preview?pool={pool_name}&file={urllib.parse.quote(file_name)}" # 传递原始 URL,不要再次编码 pdf_url = f"/static/pdfjs/web/viewer.html?file={proxy_url}" self.redirect(pdf_url) return # 设置 MIME 类型 mime_type = { '.docx': 'application/vnd.openxmlformats-officedocument.wordprocessingml.document', '.xlsx': 'application/vnd.openxmlformats-officedocument.spreadsheetml.sheet', '.pptx': 'application/vnd.openxmlformats-officedocument.presentationml.presentation', '.pdf': 'application/pdf', '.txt': 'text/plain', '.md': 'text/markdown', '.html': 'text/html', '.css': 'text/css', '.js': 'application/javascript', '.png': 'image/png', '.jpg': 'image/jpeg', '.jpeg': 'image/jpeg', '.gif': 'image/gif', '.mp4': 'video/mp4', '.webm': 'video/webm', '.ogg': 'video/ogg', '.mp3': 'audio/mpeg', '.wav': 'audio/wav', '.flac': 'audio/flac', }.get(ext, mimetypes.guess_type(file_name)[0] or 'application/octet-stream') encoded_filename = urllib.parse.quote(file_name.encode('utf-8')) self.set_header("Content-Disposition", f'inline; filename*=UTF-8\'\'{encoded_filename}') file_size = os.path.getsize(file_path) range_header = self.request.headers.get('Range') is_download = not range_header and ext in ['.mp4', '.webm', '.ogg', '.pdf'] if is_download: self.set_header('Content-Type', mime_type) self.set_header('Content-Length', str(file_size)) self.set_status(200) if os.name == 'posix': fd = os.open(file_path, os.O_RDONLY) try: await tornado.ioloop.IOLoop.current().run_in_executor( None, os.sendfile, self.request.connection.fileno(), fd, None, file_size ) finally: os.close(fd) else: with open(file_path, 'rb') as f: while True: chunk = f.read(1024 * 1024 * 4) if not chunk: break try: self.write(chunk) await self.flush() except tornado.iostream.StreamClosedError: return self.finish() elif ext in ['.mp4', '.webm', '.ogg', '.pdf', '.mp3', '.wav', '.flac']: self.set_header('Accept-Ranges', 'bytes') start = 0 end = file_size - 1 if range_header: self.set_status(206) start_bytes, end_bytes = range_header.replace('bytes=', '').split('-') start = int(start_bytes) if start_bytes else 0 end = int(end_bytes) if end_bytes else file_size - 1 self.set_header('Content-Range', f'bytes {start}-{end}/{file_size}') self.set_header("Content-Length", str(end - start + 1)) self.set_header('Content-Type', mime_type) chunk_size = 4096 * 16 async with aiofiles.open(file_path, 'rb') as f: await f.seek(start) remaining = end - start + 1 while remaining > 0: chunk = await f.read(min(chunk_size, remaining)) if not chunk: break try: self.write(chunk) await self.flush() except tornado.iostream.StreamClosedError: return remaining -= len(chunk) self.finish() elif ext == '.txt': self.set_header('Content-Type', 'text/plain; charset=UTF-8') async with aiofiles.open(file_path, 'r', encoding='utf-8') as f: content = await f.read() self.write(content) self.finish() elif ext in ['.png', '.jpg', '.jpeg', '.gif', '.md', '.pdf', '.docx', '.xlsx', '.pptx']: self.set_header('Content-Type', mime_type) async with aiofiles.open(file_path, 'rb') as f: data = await f.read() self.write(data) self.finish() else: self.set_status(400) self.write("不支持预览此文件类型") 这是我的这个方法,你在我提供的这个方法代码中修改后给我把修改后的方法代码完整的给我提供过来吧
最新发布
08-30
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值