请问下下图这是哪个类型妻子的借口 下载。

python 接口_从协议到抽象基类详解
投稿:jingxian
字体:[ ] 类型:转载 时间:
下面小编就为大家带来一篇python 接口_从协议到抽象基类详解。小编觉得挺不错的,现在就分享给大家,也给大家做个参考。一起跟随小编过来看看吧
抽象基类的常见用途:实现接口时作为超类使用。然后,说明抽象基类如何检查具体子类是否符合接口定义,以及如何使用注册机制声明一个类实现了某个接口,而不进行子类化操作。最后,说明如何让抽象基类自动“识别”任何符合接口的类——不进行子类化或注册。
Python文化中的接口和协议
接口在动态类型语言中是怎么运作的呢?首先,基本的事实是,Python语言没有 interface 关键字,而且除了抽象基类,每个类都有接口:类实现或继承的公开属性(方法或数据属性),包括特殊方法,如__getitem__ 或 __add__。
按照定义,受保护的属性和私有属性不在接口中:即便“受保护的”属性也只是采用命名约定实现的(单个前导下划线);私有属性可以轻松地访问,原因也是如此。不要违背这些约定。
另一方面,不要觉得把公开数据属性放入对象的接口中不妥,因为如果需要,总能实现读值方法和设值方法,把数据属性变成特性,使用obj.attr 句法的客户代码不会受到影响。 Vector2d 类就是这么做的,Vector2d 类的第一版,x 和 y 是公开属性。
vector2d_v0.py:x 和 y 是公开数据属性
class Vector2d:
def __init__(self, x, y):
self.x = x
self.y = y
def __iter__(self):
return (n for n in (self.x, self.y))
我们把 x 和 y 变成了只读特性。这是一项重大重构,但是 Vector2d 的接口基本没变:用户仍能读取my_vector.x 和 my_vector.y。
class Vector2d:
def __init__(self, x, y):
self.__x = x
self.__y = y
def x(self):
return self.__x
def y(self):
return self.__y
def __iter__(self):
return (i for i in (self.x, self.y))
Python喜欢序列
Python 数据模型的哲学是尽量支持基本协议。对序列来说,即便是最简单的实现,Python 也会力求做到最好。
下图展示了定义为抽象基类的 Sequence 正式接口。
Sequence 抽象基类和 collections.abc 中相关抽象类的UML 类图,箭头由子类指向超类,以斜体显示的是抽象方法
现在,看看下面🌰中的 Foo 类。它没有继承 abc.Sequence,而且只实现了序列协议的一个方法: __getitem__ (没有实现 __len__ 方法)。
&&& class Foo:
...   def __getitem__(self, pos):
...     return range(0, 30, 10)[pos]
&&& f = Foo()
&&& for i in f: print(i)
&&& 20 in f
&&& 15 in f
虽然没有 __iter__ 方法,但是 Foo 实例是可迭代的对象,因为发现有__getitem__ 方法时,Python 会调用它,传入从 0 开始的整数索引,尝试迭代对象(这是一种后备机制)。尽管没有实现 __contains__ 方法,但是 Python 足够智能,能迭代 Foo 实例,因此也能使用 in 运算符:Python 会做全面检查,看看有没有指定的元素。
综上,鉴于序列协议的重要性,如果没有 __iter__ 和 __contains__方法,Python 会调用 __getitem__ 方法,设法让迭代和 in 运算符可用。
下面的FrenchDeck 类也没有继承 abc.Sequence,但是实现了序列协议的两个方法:__getitem__ 和 __len__。
class FrenchDeck:
ranks = [str(n) for n in range(2, 11)] + list('JQKA')
suits = 'spades diamonds clubs hearts'.split()
def __init__(self):
self._cards = [Cards(rank, suit) for suit in self.suits
for rank in self.ranks]
def __len__(self):
return len(self._cards)
def __getitem__(self, pos):
return self._cards[pos]
使用猴子补丁在运行时实现协议
FrenchDeck 类有个重大缺陷:无法洗牌。如果 FrenchDeck 实例的行为像序列,那么它就不需要 shuffle 方法,因为已经有 random.shuffle 函数可用,文档中说它的作用是“就地打乱序x”(https://docs.python.org/3/library/random.html#random.shuffle)。
标准库中的 random.shuffle 函数用法如下:
&&& from random import shuffle
&&& my_list = list(range(1, 11))
&&& shuffle(my_list)
&&& my_list
[5, 7, 9, 2, 10, 1, 8, 6, 4, 3]
然而,如果尝试打乱 FrenchDeck 实例,会出现异常,如下面的 🌰 所示。
Traceback (most recent call last):
File "/Users/demon/PycharmProjects/FluentPython/接口:从协议到抽象基类/FrenchDeck.py", line 37, in &module&
shuffle(deck)
File "/Library/Frameworks/Python.framework/Versions/3.6/lib/python3.6/random.py", line 274, in shuffle
x[i], x[j] = x[j], x[i]
TypeError: 'FrenchDeck' object does not support item assignment  
错误消息相当明确,“'FrenchDeck' object does not support itemassignment”('FrenchDeck' 对象不支持为元素赋值)。这个问题的原因是,shuffle 函数要调换集合中元素的位置,而 FrenchDeck 只实现了不可变的序列协议。可变的序列还必须提供 __setitem__ 方法。
解决办法为FrenchDeck 打猴子补丁,把它变成可变的,让random.shuffle 函数能处理
from collections import namedtuple
from random import shuffle
Cards = namedtuple('Cards', ['rank', 'suit'])
class FrenchDeck:
ranks = [str(n) for n in range(2, 11)] + list('JQKA')
suits = 'spades diamonds clubs hearts'.split()
def __init__(self):
self._cards = [Cards(rank, suit) for suit in self.suits
for rank in self.ranks]
def __len__(self):
#获取长度的len
return len(self._cards)
def __getitem__(self, position): #能够支持切片取值的处理
return self._cards[position]
deck = FrenchDeck()
def set_card(deck, position, card):
#猴子不定,其实就是启动调用内部__setitem__设置值得外部函数
deck._cards[position] = card
FrenchDeck.__setitem__ = set_card
#把猴子补丁传递给内部的魔术方法
shuffle(deck)
#打乱洗牌的序列
print(deck[:5])
#获取前五个卡牌的值
以上代码的执行结果为:
[Cards(rank='K', suit='diamonds'), Cards(rank='4', suit='spades'), Cards(rank='A', suit='clubs'), Cards(rank='K', suit='spades'), Cards(rank='6', suit='clubs')]  
这里的关键是,set_card 函数要知道 deck 对象有一个名为 _cards 的属性,而且 _cards 的值必须是可变序列。然后,我们把 set_card 函数赋值给特殊方法 __setitem__,从而把它依附到 FrenchDeck 类上。这种技术叫猴子补丁:在运行时修改类或模块,而不改动源码。猴子补丁很强大,但是打补丁的代码与要打补丁的程序耦合十分紧密,而且往往要处理隐藏和没有文档的部分。
定义抽象基类的子类
在下面的🌰 中,我们明确把 FrenchDeck2 声明为collections.MutableSequence 的子类。
frenchdeck2.py:FrenchDeck2,collections.MutableSequence的子类
import collections
Card = collections.namedtuple('Card', ['rank', 'suit'])
class FrenchDeck2(collections.MutableSequence):
ranks = [str(i) for i in range(1, 11)] + list('JQKA')
suits = 'spades diamonds clubs hearts'.split()
def __init__(self):
self._cards = [Card(rank, suit) for suit in self.suits
for rank in self.ranks]
def __len__(self):
#支持查看长度
return len(self._cards)
def __getitem__(self, position):
return self._cards[position]
def __setitem__(self, position, value):
self._cards[position] = value
def __delitem__(self, position):
#但是继承MutableSequence的类必须实现 __delitem__ 方法,这是MutableSequence 类的一个抽象方法。
del self._cards[position]
def insert(self, position, value):
#此外,还要实现insert方法,这是MutableSequence类的第三个抽象方法
self._cards.insert(position, value)
Sequence 和 MutableSequence 抽象基类的方法不全是抽象的。
MutableSequence 抽象基类和 collections.abc 中它的超类的 UML 类图(箭头由子类指向祖先;以斜体显示的名称是抽象类和抽象方法)
FrenchDeck2 从 Sequence 继承了几个拿来即用的具体方法__contains__、__iter__、__reversed__、index 和count。FrenchDeck2 从MutableSequence 继承了append、extend、pop、remove 和__iadd__。
标准库中的抽象基类
从 Python 2.6 开始,标准库提供了抽象基类。大多数抽象基类在collections.abc 模块中定义,不过其他地方也有。例如,numbers和 io 包中有一些抽象基类。但是,collections.abc 中的抽象基类最常用。我们来看看这个模块中有哪些抽象基类。
collections.abc模块中的抽象基类
collections.abc 模块中各个抽象基类的 UML 类图
Iterable、Container 和 Sized
各个集合应该继承这三个抽象基类,或者至少实现兼容的协议。Iterable 通过 __iter__ 方法支持迭代,Container 通过__contains__ 方法支持 in 运算符,Sized 通过 __len__ 方法支持len() 函数。
Sequence、Mapping 和 Set
这三个是主要的不可变集合类型,而且各自都有可变的子类
MappingView
在 Python 3 中,映射方法 .items()、.keys() 和 .values() 返回的对象分别是 ItemsView、KeysView 和 ValuesView 的实例。前两个类还从 Set 类继承了丰富的接口。
Callable 和 Hashable
这两个抽象基类与集合没有太大的关系,只不过因为collections.abc 是标准库中定义抽象基类的第一个模块,而它们又太重要了,因此才把它们放到 collections.abc 模块中。我从未见过Callable 或 Hashable 的子类。这两个抽象基类的主要作用是为内置函数 isinstance 提供支持,以一种安全的方式判断对象能不能调用或散列。
注意它是 Iterable 的子类。继 collections.abc 之后,标准库中最有用的抽象基类包是numbers
抽象基类的数字塔
numbers 包(https://docs.python.org/3/library/numbers.html)定义的是“数字塔”(即各个抽象基类的层次结构是线性的),其中 Number 是位于最顶端的超类,随后是 Complex 子类,依次往下,最底端是 Integral类:
因此,如果想检查一个数是不是整数,可以使用 isinstance(x,numbers.Integral),这样代码就能接受 int、bool(int 的子类),或者外部库使用 numbers 抽象基类注册的其他类型。为了满足检查的需要,你或者你的 API 的用户始终可以把兼容的类型注册为numbers.Integral 的虚拟子类。
与之类似,如果一个值可能是浮点数类型,可以使用 isinstance(x,numbers.Real) 检查。这样代码就能接受bool、int、float、fractions.Fraction,或者外部库(如NumPy,它做了相应的注册)提供的非复数类型。
定义并使用一个抽象基类
为了证明有必要定义抽象基类,我们要在框架中找到使用它的场景。想象一下这个场景:你要在网站或移动应用中显示随机广告,但是在整个广告清单轮转一遍之前,不重复显示广告。假设我们在构建一个广告管理框架,名为 ADAM。它的职责之一是,支持用户提供随机挑选的无重复类。 为了让 ADAM 的用户明确理解“随机挑选的无重复”组件是什么意思,我们将定义一个抽象基类。
受到“栈”和“队列”(以物体的排放方式说明抽象接口)启发,我将使用现实世界中的物品命名这个抽象基类:宾果机和彩票机是随机从有限的集合中挑选物品的机器,选出的物品没有重复,直到选完为止。
我们把这个抽象基类命名为 Tombola,这是宾果机和打乱数字的滚动容器的意大利名。
Tombola 抽象基类有四个方法,其中两个是抽象方法。
.load(...):把元素放入容器。
.pick():从容器中随机拿出一个元素,返回选中的元素
另外两个是具体方法。
.loaded():如果容器中至少有一个元素,返回 True。
.inspect():返回一个有序元组,由容器中的现有元素构成,不会修改容器的内容(内部的顺序不保留)。
展示了 Tombola 抽象基类和三个具体实现。
一个抽象基类和三个子类的 UML 类图。根据 UML 的约定,Tombola 抽象基类和它的抽象方法使用斜体。虚线箭头用于表示接口实现,这里它表示 TomboList 是 Tombola 的虚拟子类,因为TomboList 是注册的
import abc
class Tombola(abc.ABC):
#自己定义的抽象基类要继承abc.ABC
@abc.abstractmethod
def load(self, iterable):
#抽象方法使用@abstractmethod装饰器标记,而且定义体中通常只有文档字符串
"""从可迭代对象中添加元素"""
@abc.abstractmethod
def pick(self):
#根据文档字符串,如果没有元素可选,应该抛出LookupError
"""随机删除元素,然后返回
如果实例为空,这个方法应该抛出'LookupError'
def loaded(self):
#抽象基类可以包含具体方法
"""如果至少有一个元素,返回`True`,否则返回`False`。"""
return bool(self.inspect())
def inspect(self):
"""返回一个有序元组,由当前元素构成。"""
items = []
while True:
items.append(self.pick())
except LookupError:
self.load(items)
#使用 .load(...)把所有元素放回去
return tuple(sorted(items))
#返回排序好的items攻loaded调用
选择使用 LookupError 异常的原因是,在 Python 的异常层次关系中,它与 IndexError 和 KeyError 有关,这两个是具体实现 Tombola的数据结构最有可能抛出的异常。据此,实现代码可能会抛出LookupError、IndexError 或 KeyError 异常。
异常类的部分层次结构
BaseException
├── SystemExit
├── KeyboardInterrupt
├── GeneratorExit
└── Exception
├── StopIteration
├── ArithmeticError
│ ├── FloatingPointError
│ ├── OverflowError
│ └── ZeroDivisionError
├── AssertionError
├── AttributeError
├── BufferError
├── EOFError
├── ImportError
├── LookupError #我们在 Tombola.inspect 方法中处理的是 LookupError 异常
│ ├── IndexError #IndexError 是 LookupError 的子类,尝试从序列中获取索引超过最后位置的元素时抛出
│ └── KeyError #使用不存在的键从映射中获取元素时,抛出 KeyError 异常
├── MemoryError
我们自己定义的 Tombola 抽象基类完成了。为了一睹抽象基类对接口所做的检查,下面我们尝试使用一个有缺陷的实现来糊弄 Tombola,如下面的 🌰 所示
不符合 Tombola 要求的子类无法蒙混过关
&&& from tombola import Tombola
&&& class Fake(Tombola):               # 把Fake声明为Tombole的子类,继承抽象类
def pick(self):
&&& Fake                         # 创建Fake类,目前木有毛线问题~
&class '__main__.Fake'&
&&& f = Fake()                     # 报错了,Python认为Fake类是抽象类,因为没有实现load方法
Traceback (most recent call last):
File "&stdin&", line 1, in &module&
TypeError: Can't instantiate abstract class Fake with abstract methods load
抽象基类句法详解
声明抽象基类最简单的方式是继承 abc.ABC 或其他抽象基类。
然而,abc.ABC 是 Python 3.4 新增的类,因此如果你使用的是旧版Python,那么无法继承现有的抽象基类。此时,必须在 class 语句中使用 metaclass= 关键字,把值设为 abc.ABCMeta(不是 abc.ABC)。在下面的🌰 ,可以写成:
class Tombola(metaclass=abc.ABCMeta):
metaclass= 关键字参数是 Python 3 引入的。在 Python 2 中必须使用__metaclass__ 类属性:
class Tombola(object): # 这是Python 2!!!
__metaclass__ = abc.ABCMeta
除了 @abstractmethod 之外,abc 模块还定义了@abstractclassmethod、@abstractstaticmethod 和@abstractproperty 三个装饰器。然而,后三个装饰器从 Python 3.3起废弃了,因为装饰器可以在 @abstractmethod 上堆叠,那三个就显得多余了。例如,声明抽象类方法的推荐方式是:
class MyABC(abc.ABC):
@classmethod
@abc.abstractmethod
def an_abstract_classmethod(cls, ...):
定义Tombola抽象基类的子类
定义好 Tombola 抽象基类之后,我们要开发两个具体子类,满足Tombola 规定的接口。
下面的🌰 中的 BingoCage 类,使用了更好的随机发生器。 BingoCage 实现了所需的抽象方法 load 和 pick,从 Tombola 中继承了 loaded 方法,覆盖了 inspect 方法,还增加了__call__ 方法。
import random
import abc
class Tombola(abc.ABC):
#自己定义的抽象基类要继承abc.ABC
@abc.abstractmethod
def load(self, iterable):
#抽象方法使用@abstractmethod装饰器标记,而且定义体中通常只有文档字符串
"""从可迭代对象中添加元素"""
@abc.abstractmethod
def pick(self):
#根据文档字符串,如果没有元素可选,应该抛出LookupError
"""随机删除元素,然后返回
如果实例为空,这个方法应该抛出'LookupError'
def loaded(self):
#抽象基类可以包含具体方法
"""如果至少有一个元素,返回`True`,否则返回`False`。"""
return bool(self.inspect())
def inspect(self):
"""返回一个有序元组,由当前元素构成。"""
items = []
while True:
items.append(self.pick())
except LookupError:
self.load(items)
#使用 .load(...)把所有元素放回去
return tuple(sorted(items))
#返回排序好的items攻loaded调用
#下面的代码应该单端放到一个py文件中,为了省事,就不在单独放到一个模块里面导入了~
class BigoCage(Tombola):
#明确指定BingoCage类扩展Tombola类
def __init__(self, items):
self._randomizer = random.SystemRandom()
#假设我们将在线上游戏中使用这个。random.SystemRandom使用os.urandom(...) 函数实现randomAPI
self._items = []
self.load(items)
#委托.load(...)方法实现初始加载
def load(self, items):
self._items.extend(items)
#如果通过load方法传递一个可迭代的对象进来,可以扩展到以后的self._items的列表中
self._randomizer.shuffle(self._items)
#没有使用random.shuffle而是使用了SystemRandom中的shuffle方法
def pick(self):
return self._items.pop()
except IndexError:
raise LookupError('pick from empty BingoCage')
def __call__(self):
self.pick()
b = BigoCage(range(10))
print(b.pick())
下面是 Tombola 接口的另一种实现,虽然与之前不同,但完全有效。LotteryBlower 打乱“数字球”后没有取出最后一个,而是取出一个随机位置上的球。
lotto.py:LotteryBlower 是 Tombola 的具体子类,覆盖了继承的 inspect 和 loaded 方法
import random
from tombola import Tombola
class LotteryBlower(Tombola):
def __init__(self, iterable):
self._balls = list(iterable)
#创建一个副本
def load(self, iterbale):
self._balls.extend(iterbale)
#把一个可迭代的对象添加到列表中
def pick(self):
position = random.randrange(len(self._balls)) #获取一个随机数
except ValueError:
raise LookupError('pick from empty LotteryBlower')
return self._balls.pop(position)
#删除列表中通过列表长度获取的随机数位置的索引值
def loaded(self):
return bool(self._balls)
def inspect(self):
return tuple(sorted(self._balls))
以上这篇python 接口_从协议到抽象基类详解就是小编分享给大家的全部内容了,希望能给大家一个参考,也希望大家多多支持脚本之家。
您可能感兴趣的文章:
大家感兴趣的内容
12345678910
最近更新的内容
常用在线小工具请问下下图这个人到底是不是湖南工学院的?_湖南工学院吧_百度贴吧
&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&&签到排名:今日本吧第个签到,本吧因你更精彩,明天继续来努力!
本吧签到人数:0成为超级会员,使用一键签到本月漏签0次!成为超级会员,赠送8张补签卡连续签到:天&&累计签到:天超级会员单次开通12个月以上,赠送连续签到卡3张
关注:87,240贴子:
请问下下图这个人到底是不是湖南工学院的?收藏
在多玩看到这个帖子。请问下下图这个到底人是不是湖南工学院的?
长沙理工大学成考本科2017年网上报名已经全面启动,报考不限学历,不限基础,含金量高.专业,免考科目一览,最快1/1.5年拿文凭,报名从速.
额额额额额额额额额额额额
登录百度帐号推荐应用请问下面截图中是什么接口?(附截图)_百度知道
请问下面截图中是什么接口?(附截图)
注:箭头所指的是什么接口?
我有更好的答案
第一个图,是电源指示灯接口第二个图,从上到下一依次是:前置音频接口SPDIF接口(光纤或同轴音频接口和串行端口接口
第一张图问了2个接口,小箭头所指的(有英文标识)。第二张图问了3个接口,小箭头所指(有英文标识)。
哦,就是第一个图少说了一个,就是前面那个是前面板控制及指示灯的接口还有疑问吗?
那个2针的指示灯接口好像有点重复9针接口中的电源指示灯?
资深电脑人
baidu.baidu百度一下箭头旁边英文&
第一个是主板电源,下面是光驱 和硬盘
为您推荐:
您可能关注的内容
换一换
回答问题,赢新手礼包springMVC框架下——通用接口之图片上传接口
时间: 00:03:19
&&&& 阅读:6437
&&&& 评论:
&&&& 收藏:0
标签:  我所想要的图片上传接口是指服务器端在完成图片上传后,返回一个可访问的图片地址。
spring mvc框架下图片上传非常简单,如下 
1 @RequestMapping(value="/uploadImg", method=RequestMethod.POST)
2 @ResponseBody
3 public String uploadImg(@RequestParam(value="img")MultipartFile img){
File f = new File("/data/images");
FileUtils.copyInputStreamToFile(img.getInputStream(), f);
}catch(Exception e){
e.printStackTrace();
return "上传成功";
非常简单吧!
1 &form action="http://localhost/component/common/uploadImg" method="post" enctype="multipart/form-data"&
头像:&input type="file" name="img" /&&br/&
&input type="image" src="./images/img_submit.gif" /&
以上仅仅只是能够上传文件而已,而我们还要能返回一个图片地址,这个图片地址要能在浏览器中直接访问,如下:
直接代码吧!
controller层
1 @RequestMapping(value="/uploadImg", method=RequestMethod.POST)
2 @ResponseBody
3 public String uploadImg(@RequestParam(value="img")MultipartFile img, HttpServletResponse response){
JSONObject result = new JSONObject();
boolean flag = true;
flag = pictureUploadService.upload(img, result);
} catch (Exception e) {
result.put("mess", "调用失败");
flag = false;
e.printStackTrace();
result.put("flag", flag);
response.setContentType("text/charset=UTF-8");
//解决跨域名访问问题
response.setHeader("Access-Control-Allow-Origin", "*");
return result.toString();
* 上传图片
* @param file
* @param params
* @throws Exception
8 public boolean upload(MultipartFile file, JSONObject params) throws Exception{
//过滤合法的文件类型
String fileName = file.getOriginalFilename();
String suffix = fileName.substring(fileName.lastIndexOf(".")+1);
String allowSuffixs = "gif,jpg,jpeg,bmp,png,ico";
if(allowSuffixs.indexOf(suffix) == -1){
params.put("resultStr", "not support the file type!");
return false;
//获取网络地址、本地地址头部
Properties config = new Properties();
config.load(this.getClass().getClassLoader().getResourceAsStream("config.properties"));
String urlPath = config.getProperty("urlRoot");
String localPath = config.getProperty("localRoot");
//创建新目录
String uri = File.separator + DateUtil.getNowDateStr(File.separator);
File dir = new File(localPath + uri);
if(!dir.exists()){
dir.mkdirs();
//创建新文件
String newFileName = StringUtil.getUniqueFileName();
File f = new File(dir.getPath() + File.separator + newFileName + "." + suffix);
//将输入流中的数据复制到新文件
FileUtils.copyInputStreamToFile(file.getInputStream(), f);
//创建Picture对象
Picture pic = new Picture();
pic.setLocalPath(f.getAbsolutePath());
pic.setName(f.getName());
pic.setUrl(urlPath + uri.replace("\\", "/") + "/" + newFileName + "." + suffix);
pic.setAddTime(new Date());
//插入到数据库
params.put("resultStr", pic.getUrl());
return true;
(暂时没有dao层,我在properties中配置网络地址的域名以及本地文件存储目录)
上传文件有几个地方需要注意:
上传文件的中文乱码(这个暂不考虑,毕竟要实现的是图片上传)
限制上传文件大小(文件过大,会导致服务器不堪重负),这个我们在spring mvc的配置文件中进行限制
1 &beans:bean id="multipartResolver" class="org.springframework.monsMultipartResolver"&
&beans:property name="defaultEncoding" value="utf-8" /&
&beans:property name="maxUploadSize" value="" /&
&beans:property name="maxInMemorySize" value="40960" /&
5 &/beans:bean&
限制上传文件类型(这个我们在service层进行处理)
如果一个文件夹下面保存超过1000个文件,就会影响文件访问性能,所以上传的文件要分散存储(这个分散策略有多种,不必拘泥于一种。我这里偷懒用了年月日作为目录层级)
* 获取当前日期字符串
* @param separator
6 public static String getNowDateStr(String separator){
Calendar now = Calendar.getInstance();
int year = now.get(Calendar.YEAR);
int month = now.get(Calendar.MONTH)+1;
int day = now.get(Calendar.DATE);
return year + separator + month + separator +
上传成功后保存的文件不能重名(即文件名要唯一)
1 //生成唯一的文件名
2 public static String getUniqueFileName(){
String str = UUID.randomUUID().toString();
return str.replace("-", "");
上传图片流程如下:
点击上传后,返回
在浏览器中输入上面的这个图片地址访问,然后出现
&&国之画&&&& &&&&chrome插件&&
版权所有 京ICP备号-2
迷上了代码!

我要回帖

更多关于 借口mp3下载 的文章

 

随机推荐