最近想给网页增加图片上传功能,具体想在上传图片的同时对图片进行日期+随机数的命名方式,网上找找了很久,教程很多,但是对我这个初学者来说很多看不懂,最后找到一篇http://www.tuicool.com/articles/jMZBby 文章,代码解释的很清楚,但是在实际操作中还是遇到一些问题,经结合实际运行中的要求,对原代码进行了修改,现将代码上传,希望以此达到抛砖引玉的作用,给正在被图片上传困扰的兄弟一些借鉴同时也希望各位达人能够给我写的拙劣的代码提些意见,在完善代码的同时能给予我一些点拨。再次感谢原作者!
#models
class Photo(models.Model):
hetongNO = models.ForeignKey(HetongGL,verbose_name=u'合同号')
name = models.CharField(max_length = 100,verbose_name="Name")
image = models.ImageField(upload_to = "photos",blank=True,null=True)
#forms
class Addphoto(ModelForm):
class Meta:
model = Photo
fields = ['hetongNO','name','image']
#views
import datetime
import random
import imghdr
import os
from django.conf import settings
import shutil
def addphoto(request):
path = settings.MEDIA_ROOT + 'photo/'
if request.method == 'POST':
form = Addphoto(request.POST,request.FILES)
if form.is_valid():
hetongNO = form.cleaned_data['hetongNO']
name = form.cleaned_data['name']
if request.FILES: #判断是否存在上传信息,否则为空
f = request.FILES['image']
ret = handle_uploaded_file(f,path)
if ret:
p = Photo(hetongNO = hetongNO,name = name,image = ret)
p.save()
messages.add_message(request, messages.SUCCESS, '数据保存成功!')
else:
messages.add_message(request, messages.SUCCESS, '上传出现问题,请重新上传,请确保上传的文件类型正确。')
else:
p = Photo(hetongNO = hetongNO,name = name,image = None)
p.save()
messages.add_message(request, messages.SUCCESS, '数据保存成功!')
return HttpResponseRedirect('/demo/')
else:
form = Addphoto()
return render_to_response('fieldtest.html',locals(),context_instance=RequestContext(request))
#将临时文件转存到指定文件夹下
def handle_uploaded_file(f,path):
if f.size >= 5 * 1024 *1024 or not handle_upload_types(f.name):
return False
file_type_name_path = handle_upload_types_finally(f) #读取临时文件的列表信息。
if not file_type_name_path:
return False
try:
if not os.path.exists(
path):
os.mkdir(path)
shutil.move(file_type_name_path[2],path) #将临时文件转存
image_path = 'photo/%s.%s' % (file_type_name_path[1],file_type_name_path[0])
return image_path
except IOError:
return False
#判断文件类型,如为exe则返回Flase
def handle_upload_types(file_name):
file_name = unicode(file_name) #将文件原始路径转为转换编码(应对原始路径中有中文字符的情况)
not_allowed_tupes = ['.exe'] #排除exe。这里想实现对文件扩展名的判断,但是没有成功,在本例中,这里实际不需要进行判断,如果上传了其他类新的文件表单会提示文件类型不符,添加这一步一是因为原代码中有,另外也想为今后处理其他文件上传积累经验。这里如何实现还请指教。
for type in not_allowed_tupes:
if file_name.endswith(type):
return False
else:
return Tru
#生成临时文件
def handle_upload_types_finally(f):
temp_name = str(datetime.date.today().strftime("%Y%m%d")+str(random.randint(1,10000))) #对文件进行改名,这里是按照日期加随机数生成一个文件名
temp_path = settings.MEDIA_ROOT + "temp/%s" % temp_name #临时文件路径(下面创建的是一个只有文件名没有扩展名的文件)
#需要先创建一个空文件然后进行写操作,很多教程都没有这一步,
我一开始也没有写,但是运行的时候提示没有对应目录或文件,后来参看官方教程,
发现明确使用了一个已经存在的文件,所以才这样解决的。是不是多此一举请达人们指教。
try:
if not os.path.exists(temp_path):
os.mknod(temp_path)
except IOError:
return False
temp_file = open(temp_path, 'wb+') #打开临时文件
for chunk in f.chunks():
temp_file.write(chunk)
temp_file.close() #完成临时文件写入
image_type = imghdr.what(temp_path) #判断文件类型(只能判断图片),这里有个问题,比如上传的是*.jpg,但是生成的文件为*.jpeg。
if not image_type:
os.remove(temp_path) #不是图片格式的删除临时文件
return False #如果不是图片则返回。
else:
file_fullname = temp_path + '.%s' % image_type #生成文件完全路径
os.rename(temp_path,file_fullname) #将临时文件转为正常文件
return image_type , temp_name ,file_fullname #返回文件类型,文件名称,文件完整路径
最后,我的开发环境为fedora20 ×64,需要pip install Pillow,这个包依赖gcc,python-dev。