精华内容
下载资源
问答
  • 为什么我使用JavaScript无法实现选择文件后把Label修改为文件名称? 我参考的https://blog.csdn.net/tanhongwei1994/article/details/85284785可是实现不了,球球大神教教我 ```html <!DOCTYPE html> <!-- ...
  • Yii2.0 自带的fileinput上传控件如何设置后选择文件后只在表单中出现文件名而不出现预览图 echo FileInput::widget([ 'name' => 'quality_report', 'options' => ['multiple' => false], 'pluginOptions' => ...
  • 问题描述: input上传如何获取文件名显示在另一个文本框中?...选择文件后。被选择文件名将自动显示在另一个 <input type="text" 。。。 先贴代码: html代码 <input type="file" i...

    问题描述:

    input上传如何获取文件名并显示在另一个文本框中?如何用JS写? 类似优酷 搜狐上传视频,选择了文件上传后,会自动将文件名显示在标题文本框中。**<input type="file"。。。选择文件后。被选择文件名将自动显示在另一个 <input type="text" 。。。

    先贴代码: html代码

            <input type="file" id="file" onchange="handleFile()">
            <input type="text" disabled="disable" value="文件名" id="fileName">

    js代码:

            var file = document.getElementById("file");
            var fileName = document.getElementById("fileName");
            function handleFile(){
                fileName.value = file.value;
            }

    你可以试一下,应该是可以的^_^

     

    原问题:https://segmentfault.com/q/1010000002753704

    我的操作:

    	        <div id="show"> 
    	        <p> 
    				<input type="button" value="上传文件" onclick="fileEle.click()" class="smt">
    				<input type="text" size="30" name="upfile" id="upfile" style="border:0px">   
    	          	<input type="file" id="fileEle" class="smt" style="margin-right:255px; display:none" formmethod="POST" 
    	          		value="上传文件" onchange="upfile.value=this.value">
    	          	<input type="button" name="button_count" class="smt" formmethod="POST" value="统计"
    	          		onclick="fileMode()">     
    	        </p>
    	        </div>
    

     

     

     

     

     

    展开全文
  • 这会在浏览器中渲染成一个文件上传字段,单击文件选择按钮会打开文件选择窗口,选择对应的文件后,被选择文件名显示在文件选择按钮旁边。 在服务器端,可以和普通数据一样获取上传文件数据并保存。不过需要考虑...

     

    文件上传

    在HTML中,渲染一个文件上传字段只需要将<input>标签的type属性设为file,即<input type=”file”>。

    这会在浏览器中渲染成一个文件上传字段,单击文件选择按钮会打开文件选择窗口,选择对应的文件后,被选择的文件名会显示在文件选择按钮旁边。

    在服务器端,可以和普通数据一样获取上传文件数据并保存。不过需要考虑安全问题,文件上传的漏洞也是比较流行的攻击方式。除了常规的CSRF防范,我们还需要重点关注这几个问题:验证文件类型、验证文件大小、过滤文件名

     

    定义上传表单

    在python表单类中创建文件上传字段时,我们使用扩展Flask-WTF提供的FileField类,它集成WTForms提供的上传字段FileField,添加了对Flask的集成。例如:

    创建上传表单:

     

    from flask_wtf.file import FileField, FileRequired, FileAllowed
    
    class UploadForm(FlaskForm):
        photo = FileField('Upload Image', validators=[FileRequired(), FileAllowed(['jpg','jpeg','png','gif'])])
        submit = SubmitField()

     

    在表单类UploadForm()中创建了一个FileField类的photo字段,用来上传图片。

    和其他字段类似,需要对文件上传字段进行验证。Flask-WTF在flask_wtf.file模块下提供了两个文件相关的验证器,用法如下:

     

    我们使用FileRequired确保提交的表单字段中包含文件数据。处于安全考虑,必须对上传的文件类型进行限制。如果用户可以上传HTML文件,而且我们同时提供了视图函数获取上传后的文件,那么很容易导致XSS攻击。使用FileAllowed设置允许的文件类型,传入一个包含允许文件类型的后缀名列表。

     

    Flask-WTF提供的FileAllowed是在服务器端验证上传文件,使用HTML5中的accept属性也可以在客户端实现简单的类型过滤。这个属性接收MIME类型字符串或文件格式后缀,多个值之间使用逗号分隔,比如:

    <input type=”file” id=”profile_pic” name=”profile_pic” accept=”.jpg, .jpeg, .png, .gif”>

     

    当用户单击文件选择按钮后,打开的文件选择窗口会默认将accept属性之外的文件过滤掉(其实没有过滤掉)。

    尽管如此,用户还是可以选择设定之外的文件,所以仍然需要在服务器端验证。

     

    验证文件大小,通过设置Flask内置的配置变量MAX_CONTENT_LENGTH,可以显示请求报文的最大长度,单位是字节,比如:

    app.config['MAX_CONTENT_LENGTH'] = 1 * 1024 * 1024

     

    当上传文件的大小超过这个限制后,flask内置的开服务器会中断连接,在生产环境的服务器上会返回413错误响应。

     

    渲染上传表单

    在新创建的upload视图里,我们实例化表单类UploadForm,然后传入模板:

    @app.route('/upload', methods=['GET', 'POST'])
    def upload():
        form = UploadForm()
        return render_template('upload.html',form = form)

     

    在upload.html中渲染上传表单

    {% from 'macros.html' import form_field %}
    
    {% extends 'base.html' %}
    {% block content %}
        <form method="post" enctype="multipart/form-data">
            {{ form.csrf_token }}
            {{ form_field(form.photo) }}<br>
            {{ form.submit }}<br>
        </form>
    {% endblock %}

     

     

    需要注意的是,当表单中包含文件上传字段时(即type属性为file的input标签)需要将表单的enctype属性设为”multipart/form-data”,这会告诉浏览器将上传数据发送到服务器,否则仅会把文件名作为表单数据提交。

     

    处理上传文件

    和普通的表单数据不同,当包含上传文件字段的表单提价后,上传的文件需要在请求对象的files属性(request.files)中获取。这个属性(request.files)是Werkzeug提供的ImmutableMultiDict字典对象,存储字段name键值和文件对象的映射,比如:

    ImmutableMultiDict([('photo', <FileStorage: u'xiaxiaoxu.JPG' (image/jpeg)>)])

     

    上传的文件会被Flask解析为Werkzeug中的FileStorage对象(werkzeug.datastructures.FileStorage)。当手动处理时,需要使用文件上传字段的name属性值作为键获取对应的文件对象。比如:

    request.files.get(‘photo’)

     

    当使用Flask-WTF时,它会自动帮我们获取对应的文件对象,这里我们仍然使用表单类属性的data属性获取上传文件。处理上传表单提交请求的upload视图函数如下:

    import os
    app.config['UPLOAD_PATH'] = os.path.join(app.root_path, 'uploads')
    
    @app.route('/upload', methods=['GET', 'POST'])
    def upload():
        form = UploadForm()
        if form.validate_on_submit():
            f = form.photo.data
            filename =random_filename(f.filename)
            f.save(os.path.join(app.config['UPLOAD_PATH'], filename))
            flash('Upload success.')
            session['filenames'] = [filename]
            return redirect(url_for('show_images'))
        return render_template('upload.html', form = form)
    
    

    里面的函数在后面说明

    当表单通过验证后,我们通过form.photo.data获取存储上传文件的FileStorage对象。接下来,我们需要处理文件名,通常有三种处理方

    处理文件名的方式

    1)使用原文件名

    如果能够确定文件的来源安全,可以直接使用原文件名,通过FileStorage对象的filename属性获取:

    filename = f.filename

     

    2)使用过滤后的文件名

    如果要支持用户上传文件,我们必须对文件名进行处理,因为攻击者可能会在文件名中加入恶意路径。比如,如果恶意用户在文件名中加入表示上级目录的..(比如../../../home/username/.bashrc或../../etc/passwd),那么当我们保存文件时,如果这里表示上级目录的../数量正确,就会导致服务器上的系统该文件被覆盖或篡改,还有可能执行恶意脚本。我们可以使用Werkzeug提供的secure_filename()函数对文件名进行过滤,传递文件名作为参数,它会过滤掉所有危险字符,返回“安全的文件名”,如下所示:

     

    >>> from werkzeug import secure_filename

    >>> secure_filename('sam!@$%^&.jpg')

    'sam.jpg'

    >>> secure_filename('sam图片.jpg')

    'sam.jpg'

    >>> 

     

    3)统一重命名

    secure_filename()函数非常方便,它会过滤掉文件名中的非ASCII字符。但如果文件名完全由非ASCII字符组成,那么会得到一个空文件名:

    >>> secure_filename('图像.jpg')

    'jpg'

     

    为了避免出现这种情况,更好的做法是使用统一的处理方式对所有上传的文件重新命名。随机文件名有很多种方式生成,下面是一个是python内置的uuid模块生成随机文件名的random_filename()函数:

    import uuid
    
    def random_filename(filename):
        ext = os.path.splitext(filename)[1]
        new_filename = uuid.uuid4().hex + ext
        return new_filename
     

    其中os.path.splitext()和uuid.uuid4()的用法如下:

    >>> import os

    >>> os.path.splitext('d://sam/sam.jpg')

    ('d://sam/sam', '.jpg')

     

    >>> import uuid

    >>> uuid.uuid4()

    UUID('b35f485e-5a79-4d98-8cac-af62be1f0a36')

    >>> uuid.uuid4().hex

    '62f65743d16e4b388f9f6eabe3f8e5b4'

     

    这个函数接收原文件名作为参数,使用内置的uuid模块中的uuid4()方法生成新的文件名,并使用hex属性获取十六进制字符串,最后返回包含后缀的新文件名。

     

    UUID(Universally Unique Identifier,通用唯一识别码)是用来表示信息的128位数字,比如用作数据库表的主键。使用标准方法生成的UUID出现重复的可能性接近0。在UUID的标准中,UUID分为5个版本,每个版本使用不同的生产方法并且适用于不同的场景。我们使用的uuid4()方法对应的第4个版本:不接受参数而生成的随机UUID。

     

    在upload视图中,我们调用这个函数获取随机文件名,传入原文件名作为参数:

    filename = random_filename(f.filename)

     

    处理完文件名后,是时候将文件保存到文件系统中了。在form目录下创建一个uploads文件夹,用于保存上传后的文件。指向这个文件夹的绝对路径存储在自定义配置变量UPLOAD_PATH中:

    app.config[‘UPLOAD_PATH’] = os.path.join(app.root_path, ‘uploads’)

    这里的路径通过app.root_path属性构造,它存储了程序实例所在脚本的绝对路径,相当于:

    os.path.abspath(os.path.dirname(__file__))。为了保存文件,需要提前手动创建这个文件夹。

    调试:

    print "__file__:",__file__
    print "app.root_path:",app.root_path
     

    结果:

    __file__: D:/flask/FLASK_PRACTICE/form/app.py

    app.root_path: D:\flask\FLASK_PRACTICE\form

     

    对FileStorage对象调用save()方法即可保存,传入包含目标文件夹绝对路径和文件名在内的完整保存路径:

    f.save(os.path.join(app.config[‘upload_path’], filename))

    文件保存后,我们希望能够显示长传后的图片,为了让上传后的文件能够通过URL获取,我们需要创建一个视图函数来返回上传后的文件,如下所示:

    @app.route('/uploads/<path:filename>')
    def get_file(filename):
        return send_from_directory(app.config['UPLOAD_PATH', filename])

     

     

    这个视图的作用与Flask内置的static视图类似,通过传入的文件路径返回对应的静态文件。在这个uploads视图中,使用Flask提供的send_from_directory()函数来获取文件,传入文件的路径和文件名作为参数。

     

    在get_file视图的URL规则中,filename变量使用了path转换器以支持传入包含斜线的路径字符串。

    upload视图里保存文件后,使用flash()发送一个提示,将文件名保存到session中,最后重定向到show_images视图。show_images视图返回的uploaded.html模板中将从session获取文件名,渲染出上传后的图片。

    flash('Upload success.')
    session['filenames'] = [filename]
    return redirect(url_for('show_images'))

     

    这里将filename作为列表传入session只是为了兼容下面的多文件上传示例,这两个视图使用同一个模板,使用session可以在模板中统一从session获取文件名列表。

     

    在uploaded.html模板里,我们将传入的文件名作为URL变量,通过上面的get_file视图获取文件URL,作为<img>标签的src属性值,如下所示:

    <img src="{{ url_for('get_file', filename=filename) }}">

    访问127.0.0.1:5000/upload,打开文件上传示例,选择文件并提交后即可看到上传后的图片。另外,在uploads文件夹中可以看到上传的文件。

     

     

     

    提交后,看到图片

     

    uploads目录下保存的文件:

     

    下面列一下涉及的文件:

    app.py:

    from flask_wtf.file import FileField, FileRequired, FileAllowed
    from flask import send_from_directory
    
    class UploadForm(FlaskForm):
        photo = FileField('Upload Image', validators=[FileRequired(), FileAllowed(['jpg','jpeg','png','gif'])])
        submit = SubmitField()
    
    import os
    app.config['UPLOAD_PATH'] = os.path.join(app.root_path, 'uploads')
    
    import uuid
    
    def random_filename(filename):
        ext = os.path.splitext(filename)[1]
        new_filename = uuid.uuid4().hex + ext
        return new_filename
    
    @app.route('/uploaded-images')
    def show_images():
        return render_template('uploaded.html')
    
    @app.route('/uploads/<path:filename>')
    def get_file(filename):
        return send_from_directory(app.config['UPLOAD_PATH'], filename)
    
    
    @app.route('/upload', methods=['GET', 'POST'])
    def upload():
        form = UploadForm()
        if form.validate_on_submit():
            f = form.photo.data
            filename =random_filename(f.filename)
            f.save(os.path.join(app.config['UPLOAD_PATH'], filename))
            flash('Upload success.')
            session['filenames'] = [filename]
            return redirect(url_for('show_images'))
        return render_template('upload.html', form = form)
    
    

    uploaded.html:

     

    {% extends 'base.html' %}
    {% from 'macros.html' import form_field %}
    
    {% block title %}Home{% endblock %}
    
    {% block content %}
    {% if session.filenames %}
    {% for filename in session.filenames %}
    <a href="{{ url_for('get_file', filename=filename) }}" target="_blank">
        <img src="{{ url_for('get_file', filename=filename) }}">
    </a>
    {% endfor %}
    {% endif %}
    {% endblock %}

     

    upload.html:

     

    {% from 'macros.html' import form_field %}
    
    {% extends 'base.html' %}
    {% block content %}
        <form method="post" enctype="multipart/form-data">
            {{ form.csrf_token }}
            {{ form_field(form.photo) }}<br>
            {{ form.submit }}<br>
        </form>
    {% endblock %}

     

    多文件上传

    因为Flask-WTF当前版本中并未添加多多文件上传到额渲染和验证支持,因此需要在视图函数中手动获取文件并进行验证。

     

    在客户端,通过在文件上传字段(type=file)加入multiple属性,就可以开启多选:

    <input type=”file” id=”file” multiple>

    创建表单类时,可以直接使用WTForms提供的MultipleFileField字段实现,添加一个DataRequired验证器来确保包含文件:

     

    from wtforms import MultipleFileField
    class MultiUploadForm(FlaskForm):
        photo = MultipleFileField('Upload Image', validators={DataRequired()})
        submit = SubmitField()

     

    表单提交时,在服务器端的程序中,对request.files属性调用getlist()方法并传入字段的name属性值会返回包含所有上传文件对象的列表。在multi_upload视图中,我们遍历这个列表,然后逐一对文件进行处理:

    from flask import url_for, request, session, flash, redirect
    from flask_wtf.csrf import validate_csrf
    from wtforms import ValidationError
    
    @app.route('/multi-upload', methods=['GET', 'POST'])
    def multi_upload():
        form = MultiUploadForm()
        if request.method == 'POST':
            filenames = []
            #验证CSRF令牌
            try:
                validate_csrf(form.csrf_token.data)
            except ValidationError:
                flash('CSRF token error.')
                return redirect(url_for('multi_upload'))
            #检查文件是否存在
            if 'photo' not in request.files:
                flash('This field is required.')
                return redirect(url_for('multi_upload'))
            for f in request.files.getlist('photo'):
                #检查文件类型
                if f and allowed_file(f.filename):
                    filename = random_filename(f.filename)
                    f.save(os.path.join(app.config['UPLOAD_PATH'], filename ))
                    filenames.append(filename)
                else:
                    flash('Invalid file type:')
                    return redirect(url_for('multi_upload'))
            flash('Upload success.')
            session['filenames'] = filenames
            return redirect(url_for('show_images'))
        return render_template('upload.html', form=form)
     

    在请求方法为POST时,我们对上传数据进行手动验证,包含下面几步:

    1)  手动调用flask_wtf.csrf.validate_csrf验证CSRF令牌,传入表单中csrf_token隐藏字段的值。如果抛出wtforms.ValidationError异常则表明验证未通过。

    2)  其中if ‘photo’ not in request.files用来确保字段中包含文件数据(相当于FileRequired验证器),如果用户没有选择文件就提交表单则request_files将是空(实际上,不选择文件,点击提交,会触发浏览器内置提示)。

    3)  if f用来确保文件对象存在,这里也可以检查f是否是FileStorage实例。

    4)  allowed_file(f.filename)调用了allowed_file()函数,传入文件名。这个函数相当于FileAllowed验证器,用来验证文件类型,返回布尔值。

     

    allowed_file()函数定义:

    app.config['ALLOWED_EXTENSIONS'] = ['png', 'jpg', 'jpeg', 'gif']
    
    def allowed_file(filename):
        return '.' in filename and filename.rsplit('.', 1)[1].lower() in app.config['ALLOWED_EXTENSIONS']

     

     

    在上面的一个验证语句里,如果没有通过验证,我们使用flash()函数显示错误消息,然后重定向到multi_uplaod视图。

     

    filesnames[]列表是为了方便测试,保存上传后的文件名到session中。

     

    访问127.0.0.1:5000/multi-upload,单击按钮选择多个文件,当上传的文件通过验证时,程序会重定向到show_images视图,这个视图返回的uploaded.html模板中将从session获取所有文件名,渲染出所有上传后的图片。

     

     

    在新版本的Flask-WTF发布后,可以和上传单个文件相同的方式处理表单。比如可以使用Flask-WTF提供的的MultipleFileField来创建多文件上传的字段,使用相应的验证器对文件进行验证。在视图函数中,可以继续使用form.validate_on_submit()来验证表单,并通过form.photot.data来获取字段的数据:包含所有上传文件对象(werkzeug.datastructures.FileStorage)的列表。

     

    多文件上传处理通常会使用JavaScript库在客户端进行预验证,并添加进度条来优化用户体验。

    转载于:https://www.cnblogs.com/xiaxiaoxu/p/10549485.html

    展开全文
  • 这会在浏览器中渲染成一个文件上传字段,单击文件选择按钮会打开文件选择窗口,选择对应的文件后,被选择文件名显示在文件选择按钮旁边。 在服务器端,可以和普通数据一样获取上传文件数据并保存。不过需要考虑...

    文件上传

    在HTML中,渲染一个文件上传字段只需要将<input>标签的type属性设为file,即<input type=”file”>。

    这会在浏览器中渲染成一个文件上传字段,单击文件选择按钮会打开文件选择窗口,选择对应的文件后,被选择的文件名会显示在文件选择按钮旁边。

    在服务器端,可以和普通数据一样获取上传文件数据并保存。不过需要考虑安全问题,文件上传的漏洞也是比较流行的攻击方式。除了常规的CSRF防范,我们还需要重点关注这几个问题:验证文件类型、验证文件大小、过滤文件名

     

    定义上传表单

    在python表单类中创建文件上传字段时,我们使用扩展Flask-WTF提供的FileField类,它集成WTForms提供的上传字段FileField,添加了对Flask的集成。例如:

    创建上传表单:

     

    from flask_wtf.file import FileField, FileRequired, FileAllowed
    
    class UploadForm(FlaskForm):
        photo = FileField('Upload Image', validators=[FileRequired(), FileAllowed(['jpg','jpeg','png','gif'])])
        submit = SubmitField()

     

    在表单类UploadForm()中创建了一个FileField类的photo字段,用来上传图片。

    和其他字段类似,需要对文件上传字段进行验证。Flask-WTF在flask_wtf.file模块下提供了两个文件相关的验证器,用法如下:

     

    我们使用FileRequired确保提交的表单字段中包含文件数据。处于安全考虑,必须对上传的文件类型进行限制。如果用户可以上传HTML文件,而且我们同时提供了视图函数获取上传后的文件,那么很容易导致XSS攻击。使用FileAllowed设置允许的文件类型,传入一个包含允许文件类型的后缀名列表。

     

    Flask-WTF提供的FileAllowed是在服务器端验证上传文件,使用HTML5中的accept属性也可以在客户端实现简单的类型过滤。这个属性接收MIME类型字符串或文件格式后缀,多个值之间使用逗号分隔,比如:

    <input type=”file” id=”profile_pic” name=”profile_pic” accept=”.jpg, .jpeg, .png, .gif”>

     

    当用户单击文件选择按钮后,打开的文件选择窗口会默认将accept属性之外的文件过滤掉(其实没有过滤掉)。

    尽管如此,用户还是可以选择设定之外的文件,所以仍然需要在服务器端验证。

     

    验证文件大小,通过设置Flask内置的配置变量MAX_CONTENT_LENGTH,可以显示请求报文的最大长度,单位是字节,比如:

    app.config['MAX_CONTENT_LENGTH'] = 1 * 1024 * 1024

     

    当上传文件的大小超过这个限制后,flask内置的开服务器会中断连接,在生产环境的服务器上会返回413错误响应。

     

    渲染上传表单

    在新创建的upload视图里,我们实例化表单类UploadForm,然后传入模板:

    @app.route('/upload', methods=['GET', 'POST'])
    def upload():
        form = UploadForm()
        return render_template('upload.html',form = form)

     

    在upload.html中渲染上传表单

    {% from 'macros.html' import form_field %}
    
    {% extends 'base.html' %}
    {% block content %}
        <form method="post" enctype="multipart/form-data">
            {{ form.csrf_token }}
            {{ form_field(form.photo) }}<br>
            {{ form.submit }}<br>
        </form>
    {% endblock %}

     

    需要注意的是,当表单中包含文件上传字段时(即type属性为file的input标签)需要将表单的enctype属性设为”multipart/form-data”,这会告诉浏览器将上传数据发送到服务器,否则仅会把文件名作为表单数据提交。

     

    处理上传文件

    和普通的表单数据不同,当包含上传文件字段的表单提价后,上传的文件需要在请求对象的files属性(request.files)中获取。这个属性(request.files)是Werkzeug提供的ImmutableMultiDict字典对象,存储字段name键值和文件对象的映射,比如:

    ImmutableMultiDict([('photo', <FileStorage: u'xiaxiaoxu.JPG' (image/jpeg)>)])

     

    上传的文件会被Flask解析为Werkzeug中的FileStorage对象(werkzeug.datastructures.FileStorage)。当手动处理时,需要使用文件上传字段的name属性值作为键获取对应的文件对象。比如:

    request.files.get(‘photo’)

     

    当使用Flask-WTF时,它会自动帮我们获取对应的文件对象,这里我们仍然使用表单类属性的data属性获取上传文件。处理上传表单提交请求的upload视图函数如下:

    import os
    app.config['UPLOAD_PATH'] = os.path.join(app.root_path, 'uploads')
    
    @app.route('/upload', methods=['GET', 'POST'])
    def upload():
        form = UploadForm()
        if form.validate_on_submit():
            f = form.photo.data
            filename =random_filename(f.filename)
            f.save(os.path.join(app.config['UPLOAD_PATH'], filename))
            flash('Upload success.')
            session['filenames'] = [filename]
            return redirect(url_for('show_images'))
        return render_template('upload.html', form = form)

     

    
     

    里面的函数在后面说明

    当表单通过验证后,我们通过form.photo.data获取存储上传文件的FileStorage对象。接下来,我们需要处理文件名,通常有三种处理方

    处理文件名的方式

    1)使用原文件名

    如果能够确定文件的来源安全,可以直接使用原文件名,通过FileStorage对象的filename属性获取:

    filename = f.filename

     

    2)使用过滤后的文件名

    如果要支持用户上传文件,我们必须对文件名进行处理,因为攻击者可能会在文件名中加入恶意路径。比如,如果恶意用户在文件名中加入表示上级目录的..(比如../../../home/username/.bashrc或../../etc/passwd),那么当我们保存文件时,如果这里表示上级目录的../数量正确,就会导致服务器上的系统该文件被覆盖或篡改,还有可能执行恶意脚本。我们可以使用Werkzeug提供的secure_filename()函数对文件名进行过滤,传递文件名作为参数,它会过滤掉所有危险字符,返回“安全的文件名”,如下所示:

     

    >>> from werkzeug import secure_filename

    >>> secure_filename('sam!@$%^&.jpg')

    'sam.jpg'

    >>> secure_filename('sam图片.jpg')

    'sam.jpg'

    >>> 

     

    3)统一重命名

    secure_filename()函数非常方便,它会过滤掉文件名中的非ASCII字符。但如果文件名完全由非ASCII字符组成,那么会得到一个空文件名:

    >>> secure_filename('图像.jpg')

    'jpg'

     

    为了避免出现这种情况,更好的做法是使用统一的处理方式对所有上传的文件重新命名。随机文件名有很多种方式生成,下面是一个是python内置的uuid模块生成随机文件名的random_filename()函数:

    import uuid
    
    def random_filename(filename):
        ext = os.path.splitext(filename)[1]
        new_filename = uuid.uuid4().hex + ext
        return new_filename
     

    其中os.path.splitext()和uuid.uuid4()的用法如下:

    >>> import os

    >>> os.path.splitext('d://sam/sam.jpg')

    ('d://sam/sam', '.jpg')

     

    >>> import uuid

    >>> uuid.uuid4()

    UUID('b35f485e-5a79-4d98-8cac-af62be1f0a36')

    >>> uuid.uuid4().hex

    '62f65743d16e4b388f9f6eabe3f8e5b4'

    
     

    这个函数接收原文件名作为参数,使用内置的uuid模块中的uuid4()方法生成新的文件名,并使用hex属性获取十六进制字符串,最后返回包含后缀的新文件名。

     

    UUID(Universally Unique Identifier,通用唯一识别码)是用来表示信息的128位数字,比如用作数据库表的主键。使用标准方法生成的UUID出现重复的可能性接近0。在UUID的标准中,UUID分为5个版本,每个版本使用不同的生产方法并且适用于不同的场景。我们使用的uuid4()方法对应的第4个版本:不接受参数而生成的随机UUID。

     

    在upload视图中,我们调用这个函数获取随机文件名,传入原文件名作为参数:

    filename = random_filename(f.filename)

     

    处理完文件名后,是时候将文件保存到文件系统中了。在form目录下创建一个uploads文件夹,用于保存上传后的文件。指向这个文件夹的绝对路径存储在自定义配置变量UPLOAD_PATH中:

    app.config[‘UPLOAD_PATH’] = os.path.join(app.root_path, ‘uploads’)

    这里的路径通过app.root_path属性构造,它存储了程序实例所在脚本的绝对路径,相当于:

    os.path.abspath(os.path.dirname(__file__))。为了保存文件,需要提前手动创建这个文件夹。

    调试:

    print "__file__:",__file__
    print "app.root_path:",app.root_path
     

    结果:

    __file__: D:/flask/FLASK_PRACTICE/form/app.py

    app.root_path: D:\flask\FLASK_PRACTICE\form

     

    对FileStorage对象调用save()方法即可保存,传入包含目标文件夹绝对路径和文件名在内的完整保存路径:

    f.save(os.path.join(app.config[‘upload_path’], filename))

    文件保存后,我们希望能够显示长传后的图片,为了让上传后的文件能够通过URL获取,我们需要创建一个视图函数来返回上传后的文件,如下所示:

    @app.route('/uploads/<path:filename>')
    def get_file(filename):
        return send_from_directory(app.config['UPLOAD_PATH', filename])

     

     

    这个视图的作用与Flask内置的static视图类似,通过传入的文件路径返回对应的静态文件。在这个uploads视图中,使用Flask提供的send_from_directory()函数来获取文件,传入文件的路径和文件名作为参数。

     

    在get_file视图的URL规则中,filename变量使用了path转换器以支持传入包含斜线的路径字符串。

    upload视图里保存文件后,使用flash()发送一个提示,将文件名保存到session中,最后重定向到show_images视图。show_images视图返回的uploaded.html模板中将从session获取文件名,渲染出上传后的图片。

    flash('Upload success.')
    session['filenames'] = [filename]
    return redirect(url_for('show_images'))

     

    这里将filename作为列表传入session只是为了兼容下面的多文件上传示例,这两个视图使用同一个模板,使用session可以在模板中统一从session获取文件名列表。

     

    在uploaded.html模板里,我们将传入的文件名作为URL变量,通过上面的get_file视图获取文件URL,作为<img>标签的src属性值,如下所示:

    <img src="{{ url_for('get_file', filename=filename) }}">

    访问127.0.0.1:5000/upload,打开文件上传示例,选择文件并提交后即可看到上传后的图片。另外,在uploads文件夹中可以看到上传的文件。

     

     

     

    提交后,看到图片

     

    uploads目录下保存的文件:

     

    下面列一下涉及的文件:

    app.py:

    from flask_wtf.file import FileField, FileRequired, FileAllowed
    from flask import send_from_directory
    
    class UploadForm(FlaskForm):
        photo = FileField('Upload Image', validators=[FileRequired(), FileAllowed(['jpg','jpeg','png','gif'])])
        submit = SubmitField()
    
    import os
    app.config['UPLOAD_PATH'] = os.path.join(app.root_path, 'uploads')
    
    import uuid
    
    def random_filename(filename):
        ext = os.path.splitext(filename)[1]
        new_filename = uuid.uuid4().hex + ext
        return new_filename
    
    @app.route('/uploaded-images')
    def show_images():
        return render_template('uploaded.html')
    
    @app.route('/uploads/<path:filename>')
    def get_file(filename):
        return send_from_directory(app.config['UPLOAD_PATH'], filename)
    
    
    @app.route('/upload', methods=['GET', 'POST'])
    def upload():
        form = UploadForm()
        if form.validate_on_submit():
            f = form.photo.data
            filename =random_filename(f.filename)
            f.save(os.path.join(app.config['UPLOAD_PATH'], filename))
            flash('Upload success.')
            session['filenames'] = [filename]
            return redirect(url_for('show_images'))
        return render_template('upload.html', form = form)

     

    
     

    uploaded.html:

     

    {% extends 'base.html' %}
    {% from 'macros.html' import form_field %}
    
    {% block title %}Home{% endblock %}
    
    {% block content %}
    {% if session.filenames %}
    {% for filename in session.filenames %}
    <a href="{{ url_for('get_file', filename=filename) }}" target="_blank">
        <img src="{{ url_for('get_file', filename=filename) }}">
    </a>
    {% endfor %}
    {% endif %}
    {% endblock %}

     

     

    upload.html:

    {% from 'macros.html' import form_field %}
    
    {% extends 'base.html' %}
    {% block content %}
        <form method="post" enctype="multipart/form-data">
            {{ form.csrf_token }}
            {{ form_field(form.photo) }}<br>
            {{ form.submit }}<br>
        </form>
    {% endblock %}

     

     

    多文件上传

    因为Flask-WTF当前版本中并未添加多多文件上传到额渲染和验证支持,因此需要在视图函数中手动获取文件并进行验证。

     

    在客户端,通过在文件上传字段(type=file)加入multiple属性,就可以开启多选:

    <input type=”file” id=”file” multiple>

    创建表单类时,可以直接使用WTForms提供的MultipleFileField字段实现,添加一个DataRequired验证器来确保包含文件:

     

    from wtforms import MultipleFileField
    class MultiUploadForm(FlaskForm):
        photo = MultipleFileField('Upload Image', validators={DataRequired()})
        submit = SubmitField()

     

    表单提交时,在服务器端的程序中,对request.files属性调用getlist()方法并传入字段的name属性值会返回包含所有上传文件对象的列表。在multi_upload视图中,我们遍历这个列表,然后逐一对文件进行处理:

    from flask import url_for, request, session, flash, redirect
    from flask_wtf.csrf import validate_csrf
    from wtforms import ValidationError
    
    @app.route('/multi-upload', methods=['GET', 'POST'])
    def multi_upload():
        form = MultiUploadForm()
        if request.method == 'POST':
            filenames = []
            #验证CSRF令牌
            try:
                validate_csrf(form.csrf_token.data)
            except ValidationError:
                flash('CSRF token error.')
                return redirect(url_for('multi_upload'))
            #检查文件是否存在
            if 'photo' not in request.files:
                flash('This field is required.')
                return redirect(url_for('multi_upload'))
            for f in request.files.getlist('photo'):
                #检查文件类型
                if f and allowed_file(f.filename):
                    filename = random_filename(f.filename)
                    f.save(os.path.join(app.config['UPLOAD_PATH'], filename ))
                    filenames.append(filename)
                else:
                    flash('Invalid file type:')
                    return redirect(url_for('multi_upload'))
            flash('Upload success.')
            session['filenames'] = filenames
            return redirect(url_for('show_images'))
        return render_template('upload.html', form=form)

     

    
     

    在请求方法为POST时,我们对上传数据进行手动验证,包含下面几步:

    1)  手动调用flask_wtf.csrf.validate_csrf验证CSRF令牌,传入表单中csrf_token隐藏字段的值。如果抛出wtforms.ValidationError异常则表明验证未通过。

    2)  其中if ‘photo’ not in request.files用来确保字段中包含文件数据(相当于FileRequired验证器),如果用户没有选择文件就提交表单则request_files将是空(实际上,不选择文件,点击提交,会触发浏览器内置提示)。

    3)  if f用来确保文件对象存在,这里也可以检查f是否是FileStorage实例。

    4)  allowed_file(f.filename)调用了allowed_file()函数,传入文件名。这个函数相当于FileAllowed验证器,用来验证文件类型,返回布尔值。

     

    allowed_file()函数定义:

    app.config['ALLOWED_EXTENSIONS'] = ['png', 'jpg', 'jpeg', 'gif']
    
    def allowed_file(filename):
        return '.' in filename and filename.rsplit('.', 1)[1].lower() in app.config['ALLOWED_EXTENSIONS']

     

     

    在上面的一个验证语句里,如果没有通过验证,我们使用flash()函数显示错误消息,然后重定向到multi_uplaod视图。

     

    filesnames[]列表是为了方便测试,保存上传后的文件名到session中。

     

    访问127.0.0.1:5000/multi-upload,单击按钮选择多个文件,当上传的文件通过验证时,程序会重定向到show_images视图,这个视图返回的uploaded.html模板中将从session获取所有文件名,渲染出所有上传后的图片。

     

     

    在新版本的Flask-WTF发布后,可以和上传单个文件相同的方式处理表单。比如可以使用Flask-WTF提供的的MultipleFileField来创建多文件上传的字段,使用相应的验证器对文件进行验证。在视图函数中,可以继续使用form.validate_on_submit()来验证表单,并通过form.photot.data来获取字段的数据:包含所有上传文件对象(werkzeug.datastructures.FileStorage)的列表。

     

    多文件上传处理通常会使用JavaScript库在客户端进行预验证,并添加进度条来优化用户体验。

    展开全文
  • Layui原生upload模块不支持文件上传进度条显示,百度,谷歌找了一下不太适用。后面找到一个别人修改好的JS,替换上去,修改一下页面显示即可使用,一下是部分代码HTML:选择多文件文件名大小上传进度状态操作开始上传...

    Layui原生upload模块不支持文件上传进度条显示,百度,谷歌找了一下不太适用。后面找到一个别人修改好的JS,替换上去,修改一下页面显示即可使用,一下是部分代码

    005OiRqWgy1g2cg43c8lvj30wq081mxf.jpg

    HTML:

    选择多文件

    文件名大小上传进度状态操作

    开始上传

    JS部分:

    var files;

    //多文件列表示例

    var demoListView = $('#demoList')

    , uploadListIns = upload.render({

    elem: '#fileList'

    , size: 102400 //限制文件大小,单位 KB

    , exts: 'zip|rar|7z|doc|docx|pdf|txt|xls|ppt|xlsx|pptx|img|jpg|png|gif|bmp|jpeg' //只允许上传压缩文件

    , url: webroot + "/guarantee/upload/uploadFile?userid=123456"

    , accept: 'file'

    , multiple: true

    , auto: false

    , bindAction: '#fileListAction'

    , xhr: xhrOnProgress

    , progress: function (value) {//上传进度回调 value进度值

    element.progress('demoList', value + '%')//设置页面进度条

    }, xhr: function (index, e) {

    var percent = e.loaded / e.total;//计算百分比

    percent = parseFloat(percent.toFixed(2));

    element.progress('progress_' + index + '', percent * 100 + '%');

    console.log("-----" + percent);

    }

    // , data: JSON.stringify(Param)

    , choose: function (obj) {

    var files = this.files = obj.pushFile(); //将每次选择的文件追加到文件队列

    //读取本地文件

    obj.preview(function (index, file, result) {

    var tr = $(['

    '

    , '

    ' + file.name + ''

    , '

    ' + (file.size / 1014).toFixed(1) + 'kb'

    , '

    '

    , '

    等待上传'

    , '

    '

    , '重传'

    , '删除'

    , '

    '

    , '

    '].join(''));

    //单个重传

    tr.find('.demo-reload').on('click', function () {

    obj.upload(index, file);

    });

    //删除

    tr.find('.demo-delete').on('click', function () {

    delete files[index]; //删除对应的文件

    tr.remove();

    uploadListIns.config.elem.next()[0].value = ''; //清空 input file 值,以免删除后出现同名文件不可选

    });

    demoListView.append(tr);

    });

    }

    ,

    before: function (obj) {

    this.data = {

    "BUSINESS_ID": BUSINESS_ID,

    "FLOW_ID": FLOW_ID,

    "FLOW_NODE_ID": FLOW_NODE_ID,

    "FILE_TYPE": FILE_TYPE

    }///携带额外的数据

    }

    ,

    done: function (res, index, upload) {

    if (res.code == 0) { //上传成功

    var tr = demoListView.find('tr#upload-' + index)

    , tds = tr.children();

    tds.eq(3).html('上传成功');

    tds.eq(4).html(''); //清空操作

    var url = webroot + "/guarantee/itemFile/getItemFileByFlow?FLOW_ID=" + FLOW_ID + "&BUSINESS_ID=" + BUSINESS_ID + "&FLOW_NODE_ID=" + FLOW_NODE_ID + "&FILE_TYPE=" + FILE_TYPE

    //刷新表格

    table.reload('itemFileList', {

    url: url

    , where: {} //设定异步数据接口的额外参数

    //,height: 300

    });

    return delete this.files[index]; //删除文件队列已经上传成功的文件

    } else if (res.code == -1) {

    layer.msg(res.msg);

    }

    this.error(index, upload);

    }

    ,

    error: function (index, upload) {

    var tr = demoListView.find('tr#upload-' + index)

    , tds = tr.children();

    tds.eq(2).html('上传失败');

    tds.eq(3).find('.demo-reload').removeClass('layui-hide'); //显示重传

    }

    })

    ;

    注:还需替换layui的upload模块的upload.js文件

    作者:onlooker

    来源:三无青年博客br

    原文:https://www.35youth.cn/644.html

    版权声明:本文为博主原创文章,转载请附上博文链接!

    展开全文
  • 上传文件

    2015-08-10 15:54:45
    详述一下php上传文件的方法 ...用该控件选择了一个文件后,文件会被存储到服务器下特定的“上传临时文件夹”。在php.ini中有配置: upload_tmp_dir = "\xampp\tmp" 。 同时会添加文件信息到$_FIL
  • 需求:通过前台选择图片,上传到服务器文件的路径保存数据库,下次访问根据数据库路径能正确显示。 先从数据库开始: 基本需要包含以下的字段:name(文件名),path(路径),设置为varchar类型就可以。 然后就是...
  • Java多文件上传下载

    2018-10-11 22:22:21
    先上图,这是一个用MyEclipse写的文件上传和下载。 下图是上传的界面,点击按钮可以选择文件。(页面比较丑,勿喷) 下图是上传多个文件,点击“单击此处添加更多文件”,则会出现多个按钮,选择多个文件,不...
  • 文件上传------图片

    2017-01-12 11:57:00
    文件上传,拿上传图片做个例子 首先要写个form表单,之前是提交数据的,现在要上传文件提交图片,所以要在后面多加一个属性 然后再选择文件,最后上传 来看一下第一个页面的代码部分 运行看一下效果 在...
  • Layui原生upload模块不支持文件上传进度条显示,百度,谷歌找了一下不太适用。后面找到一个别人修改好的JS,替换上去,修改一下页面显示即可使用,一下是部分代码HTML:选择多文件文件名大小上传进度状态操作开始上传...
  • 上传文件到Web服务器

    热门讨论 2012-01-04 01:14:53
    首先在“文件名”文本框中输入保存到服务器上的文件名,然后单击“浏览”按钮选择要上传的文件,选择完成该文件的路径将显示在“选择文件”文本框中,最后单击“提交”按钮,将所选择的文件上传到服务器上,程序...
  • 我想实现一个文件上传的功能: (1) 选择一个文件A. 点击选择按钮. 将文件A的路径显示面板上. (2) 文件名的后面带有删除的图标. 表示可删除[color=blue]准备上传[/color]的文件. (3) 可选择多个文件.如选择一...
  • java io流文件操作是很基础的东西,最近正好写了一整套功能,上传,在页面显示文件名、路径、上层目录,并提供下载,删除功能,需求挺简单,代码也不复杂,在这里提供一下,也算作个笔记。 1.文件上传 前端代码:...
  • 1. 点击上传文件button出现弹窗,弹窗内有选择文件和开始上传button。 2. 每个文件显示序号、文件名、进度条、上传操作按钮(开始/暂停、删除)。 3. 选择好文件之后点击开始上传,文件按照顺序自动从第一个开始...
  • 最近学习的过程中遇到了上传文件后文件选择框依旧显示上传文件的文件名的问题。 亲测有效 Html代码: <input type="file" name="resourceFile" id="resourceFile"> JS代码 //Chrome $("#resourceFile")....
  • 我在做一个多文件上传,整体用的EXT,所以想用EXT的异步请求完成上传,上传没问题,就是上传完了,不执行回调函数,老自动弹一个下载"uploadFile.action"文件,其实就是一个json,好像是根本没执行回调函数,求各位...
  • 在后台上传商品图片的时候,如果你选择一个中文名称的图片,那么上传后会产生乱码,导致图片显示不出来。 下面说一种解决办法:使用“年月日时分秒 + 6个随机字符”做为文件名,如 20101016135632jusv3x.jpg 打开...
  •  }  // 没有文件上传  if (fileList == null || fileList.size() == 0) {  out.println("请选择上传文件<p />");  out.println("<a href=\"upload.html\" target=\"_top\">返回<...
  • springboot框架下的上传下载

    万次阅读 2015-07-27 16:19:25
    前端样式如上所示,点击"导入模板文件",浏览选择文件,点击“导入”则上传文件信息到服务器,当上传成功,在右侧显示文件名,并且提供下载功能。 上传样式 厂商模板文件
  • 上传附件可能是CRM里比较常用的一个需求了,本文将介绍如何在CRM里实现附件的上传、...先点击上面的上传按钮,然后就会弹出一个上传附件的界面,选择需要上传文件,填写文件名,点击上传,成功会在下面的文件g...
  • Vue+SpringBoot实现图片上传和回显

    千次阅读 2019-08-28 15:19:46
    点击Vue图标,选择电脑中图片,选中把图片替换为选中图片 ...上传图片成功,在旁边显示上传成功的图片 点击Vue图标,选择电脑中图片,选中把图片替换为选中图片: <template> &l...
  • .htaccess文件通过ftp上传到linux服务器,马上消失。通常情况下, 一些服务器上会隐藏着一些以点开始的的文件名, 常见的如 ".htaccess" 或 ".profile"。 我们可以通过CuteFTP显示这些隐藏文件,操作步骤如下: 1...
  • 上传附件界面设计

    千次阅读 2011-06-22 23:08:00
    在完成出警信息界面设计再思考如何方便的上传办案资料,采用Tlistview显示已经上传的附件,采用拖动的方法以及打开opendialg方法可以选择多个文件,得到这组文件文件名等信息,现在的问题是如何像资源管理器一样...
  • 1、IE6浏览器下文件的路径显示的是物理路径,需要进行转换 2、IIS7.0 配置时要选择经典模式 3、web.config httpRuntime 要配置好,主要设置限制上传文件的大小 4、c#下载文件路径提示页面不存在问题 解决方法:...
  • 点击页面中最右边列的向右箭头或“下载Excel”链接,可以选择显示/下载的列 </font></font>]]> <![CDATA[<font color='#3366FF'><i>其中工号查询条件采用任意位置匹配,中文名查询条件采用起始位置...
  • 在后台上传商品图片的时候,如果你选择一个中文名称的图片,那么上传后会产生乱码,导致图片显示不出来。  下面说一种解决办法: 使用“年月日时分秒 + 3个随机字符”做为文件名,如 20161016135632123.jpg 打开...
  • 在后台上传商品图片的时候,如果你选择一个中文名称的图片,那么上传后会产生乱码,导致图片显示不出来。 下面说一种解决办法: 使用“年月日时分秒 + 6个随机字符”做为文件名,如 20101016135632jusv3x.jpg 打开...

空空如也

空空如也

1 2 3 4 5 ... 8
收藏数 154
精华内容 61
关键字:

文件上传选择文件后显示文件名