iis服务器助手广告广告
返回顶部
首页 > 资讯 > 精选 >Flask中的请求上下文和应用上下文对象如何理解
  • 772
分享到

Flask中的请求上下文和应用上下文对象如何理解

2023-06-17 04:06:14 772人浏览 泡泡鱼
摘要

这篇文章将为大家详细讲解有关flask中的请求上下文和应用上下文对象如何理解,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。在Flask中处理请求时,应用会生成一个“请求上下文”对象。整个请求

这篇文章将为大家详细讲解有关flask中的请求上下文和应用上下文对象如何理解,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。

在Flask中处理请求时,应用会生成一个“请求上下文”对象。整个请求的处理过程,都会在这个上下文对象中进行。这保证了请求的处理过程不被干扰。处理请求的具体代码如下:

def wsgi_app(self, environ, start_response):      with self.request_context(environ):          # with语句中生成一个`response`对象          ...      return response(environ, start_response)

在Flask  0.9版本之前,应用只有“请求上下文”对象,它包含了和请求处理相关的信息。同时Flask还根据werkzeug.local模块中实现的一种数据结构LocalStack用来存储“请求上下文”对象。在0.9版本中,Flask又引入了“应用上下文”的概念。下面主要Flask中的这两个“上下文”对象。

LocalStack

在介绍“请求上下文”和“应用上下文”之前,我们对LocalStack简要做一个回顾。在Werkzeug库——local模块一文中,我们讲解了werkzeug.local模块中实现的三个类Local、LocalStack和LocalProxy。关于它们的概念和详细介绍,可以查看上面的文章。这里,我们用一个例子来说明Flask中使用的一种数据结构LocalStack。

>>> from werkzeug.local import LocalStack  >>> import threading     # 创建一个`LocalStack`对象  >>> local_stack = LocalStack()  # 查看local_stack中存储的信息  >>> local_stack._local.__storage__  {}     # 定义一个函数,这个函数可以向`LocalStack`中添加数据  >>> def worker(i):          local_stack.push(i)     # 使用3个线程运行函数`worker`  >>> for i in range(3):          t = threading.Thread(target=worker, args=(i,))          t.start()     # 再次查看local_stack中存储的信息  >>> local_stack._local.__storage__  {<greenlet.greenlet at 0x4bee5a0>: {'stack': [2]},  <greenlet.greenlet at 0x4bee638>: {'stack': [1]},  <greenlet.greenlet at 0x4bee6d0>: {'stack': [0]}  }

由上面的例子可以看出,存储在LocalStack中的信息以字典的形式存在:键为线程/协程的标识数值,值也是字典形式。每当有一个线程/协程上要将一个对象push进LocalStack栈中,会形成如上一个“键-值”对。这样的一种结构很好地实现了线程/协程的隔离,每个线程/协程都会根据自己线程/协程的标识数值确定存储在栈结构中的值。

LocalStack还实现了push、pop、top等方法。其中top方法永远指向栈顶的元素。栈顶的元素是指当前线程/协程中***被推入栈中的元素,即local_stack._local.stack[-1](注意,是stack键对应的对象中***被推入的元素)。

请求上下文

Flask中所有的请求处理都在“请求上下文”中进行,在它设计之初便就有这个概念。由于0.9版本代码比较复杂,这里还是以0.1版本的代码为例进行说明。本质上这两个版本的“请求上下文”的运行原理没有变化,只是新版本增加了一些功能,这点在后面再进行解释。

请求上下文&mdash;&mdash;0.1版本

# Flask v0.1  class _RequestContext(object):      """The request context contains all request relevant infORMation.  It is      created at the beginning of the request and pushed to the      `_request_ctx_stack` and removed at the end of it.  It will create the      URL adapter and request object for the WSGI environment provided.      """         def __init__(self, app, environ):          self.app = app          self.url_adapter = app.url_map.bind_to_environ(environ)          self.request = app.request_class(environ)          self.session = app.open_session(self.request)          self.g = _RequestGlobals()          self.flashes = None         def __enter__(self):          _request_ctx_stack.push(self)         def __exit__(self, exc_type, exc_value, tb):          # do not pop the request stack if we are in debug mode and an          # exception happened.  This will allow the debugger to still          # access the request object in the interactive shell.          if tb is None or not self.app.debug:              _request_ctx_stack.pop()

由上面“请求上下文”的实现可知:

  • “请求上下文”是一个上下文对象,实现了__enter__和__exit__方法。可以使用with语句构造一个上下文环境。

  • 进入上下文环境时,_request_ctx_stack这个栈中会推入一个_RequestContext对象。这个栈结构就是上面讲的LocalStack栈。

  • 推入栈中的_RequestContext对象有一些属性,包含了请求的的所有相关信息。例如app、request、session、g、flashes。还有一个url_adapter,这个对象可以进行URL匹配。

  • 在with语句构造的上下文环境中可以进行请求处理。当退出上下文环境时,_request_ctx_stack这个栈会销毁刚才存储的上下文对象。

  • 以上的运行逻辑使得请求的处理始终在一个上下文环境中,这保证了请求处理过程不被干扰,而且请求上下文对象保存在LocalStack栈中,也很好地实现了线程/协程的隔离。

以下是一个简单的例子:

# example - Flask v0.1  >>> from flask import Flask, _request_ctx_stack  >>> import threading  >>> app = Flask(__name__)  # 先观察_request_ctx_stack中包含的信息  >>> _request_ctx_stack._local.__storage__  {}     # 创建一个函数,用于向栈中推入请求上下文  # 本例中不使用`with`语句  >>> def worker():          # 使用应用的test_request_context()方法创建请求上下文          request_context = app.test_request_context()          _request_ctx_stack.push(request_context)     # 创建3个进程分别执行worker方法  >>> for i in range(3):          t = threading.Thread(target=worker)          t.start()     # 再观察_request_ctx_stack中包含的信息  >>> _request_ctx_stack._local.__storage__  {<greenlet.greenlet at 0x5e45df0>: {'stack': [<flask._RequestContext at 0x710c668>]},  <greenlet.greenlet at 0x5e45e88>: {'stack': [<flask._RequestContext at 0x7107f28>]},  <greenlet.greenlet at 0x5e45f20>: {'stack': [<flask._RequestContext at 0x71077f0>]}  }

上面的结果显示:_request_ctx_stack中为每一个线程创建了一个“键-值”对,每一“键-值”对中包含一个请求上下文对象。如果使用with语句,在离开上下文环境时栈中销毁存储的上下文对象信息。

请求上下文&mdash;&mdash;0.9版本

在0.9版本中,Flask引入了“应用上下文”的概念,这对“请求上下文”的实现有一定的改变。这个版本的“请求上下文”也是一个上下文对象。在使用with语句进入上下文环境后,_request_ctx_stack会存储这个上下文对象。不过与0.1版本相比,有以下几点改变:

  • 请求上下文实现了push、pop方法,这使得对于请求上下文的操作更加的灵活;

  • 伴随着请求上下文对象的生成并存储在栈结构中,Flask还会生成一个“应用上下文”对象,而且“应用上下文”对象也会存储在另一个栈结构中去。这是两个版本***的不同。

我们先看一下0.9版本相关的代码:

# Flask v0.9  def push(self):      """Binds the request context to the current context."""      top = _request_ctx_stack.top      if top is not None and top.preserved:          top.pop()         # Before we push the request context we have to ensure that there      # is an application context.      app_ctx = _app_ctx_stack.top      if app_ctx is None or app_ctx.app != self.app:          app_ctx = self.app.app_context()          app_ctx.push()          self._implicit_app_ctx_stack.append(app_ctx)      else:          self._implicit_app_ctx_stack.append(None)         _request_ctx_stack.push(self)         self.session = self.app.open_session(self.request)      if self.session is None:          self.session = self.app.make_null_session()

我们注意到,0.9版本的“请求上下文”的pop方法中,当要将一个“请求上下文”推入_request_ctx_stack栈中的时候,会先检查另一个栈_app_ctx_stack的栈顶是否存在“应用上下文”对象或者栈顶的“应用上下文”对象的应用是否是当前应用。如果不存在或者不是当前对象,Flask会自动先生成一个“应用上下文”对象,并将其推入_app_ctx_stack中。

我们再看离开上下文时的相关代码:

# Flask v0.9  def pop(self, exc=None):      """Pops the request context and unbinds it by doing that.  This will      also trigger the execution of functions reGIStered by the      :meth:`~flask.Flask.teardown_request` decorator.         .. versionchanged:: 0.9         Added the `exc` argument.      """      app_ctx = self._implicit_app_ctx_stack.pop()         clear_request = False      if not self._implicit_app_ctx_stack:          self.preserved = False          if exc is None:              exc = sys.exc_info()[1]          self.app.do_teardown_request(exc)          clear_request = True         rv = _request_ctx_stack.pop()      assert rv is self, 'Popped wrong request context.  (%r instead of %r)'          % (rv, self)         # get rid of circular dependencies at the end of the request      # so that we don't require the GC to be active.      if clear_request:          rv.request.environ['werkzeug.request'] = None         # Get rid of the app as well if necessary.      if app_ctx is not None:          app_ctx.pop(exc)

上面代码中的细节先不讨论。注意到当要离开以上“请求上下文”环境的时候,Flask会先将“请求上下文”对象从_request_ctx_stack栈中销毁,之后会根据实际的情况确定销毁“应用上下文”对象。

以下还是以一个简单的例子进行说明:

# example - Flask v0.9  >>> from flask import Flask, _request_ctx_stack, _app_ctx_stack  >>> app = Flask(__name__)     # 先检查两个栈的内容  >>> _request_ctx_stack._local.__storage__  {}  >>> _app_ctx_stack._local.__storage__  {}     # 生成一个请求上下文对象  >>> request_context = app.test_request_context()  >>> request_context.push()     # 请求上下文推入栈后,再次查看两个栈的内容  >>> _request_ctx_stack._local.__storage__  {<greenlet.greenlet at 0x6eb32a8>: {'stack': [<RequestContext 'Http://localhost/' [GET] of __main__>]}}  >>> _app_ctx_stack._local.__storage__  {<greenlet.greenlet at 0x6eb32a8>: {'stack': [<flask.ctx.AppContext at 0x5c96a58>]}}     >>> request_context.pop()     # 销毁请求上下文时,再次查看两个栈的内容  >>> _request_ctx_stack._local.__storage__  {}  >>> _app_ctx_stack._local.__storage__  {}

应用上下文

上部分中简单介绍了“应用上下文”和“请求上下文”的关系。那什么是“应用上下文”呢?我们先看一下它的类:

class AppContext(object):      """The application context binds an application object implicitly      to the current thread or greenlet, similar to how the      :class:`RequestContext` binds request information.  The application      context is also implicitly created if a request context is created      but the application is not on top of the individual application      context.      """         def __init__(self, app):          self.app = app          self.url_adapter = app.create_url_adapter(None)             # Like request context, app contexts can be pushed multiple times          # but there a basic "refcount" is enough to track them.          self._refcnt = 0         def push(self):          """Binds the app context to the current context."""          self._refcnt += 1          _app_ctx_stack.push(self)         def pop(self, exc=None):          """Pops the app context."""          self._refcnt -= 1          if self._refcnt <= 0:              if exc is None:                  exc = sys.exc_info()[1]              self.app.do_teardown_appcontext(exc)          rv = _app_ctx_stack.pop()          assert rv is self, 'Popped wrong app context.  (%r instead of %r)' \              % (rv, self)         def __enter__(self):

由以上代码可以看出:“应用上下文”也是一个上下文对象,可以使用with语句构造一个上下文环境,它也实现了push、pop等方法。“应用上下文”的构造函数也和“请求上下文”类似,都有app、url_adapter等属性。“应用上下文”存在的一个主要功能就是确定请求所在的应用。

然而,以上的论述却又让人产生这样的疑问:既然“请求上下文”中也包含app等和当前应用相关的信息,那么只要调用_request_ctx_stack.top.app或者魔法current_app就可以确定请求所在的应用了,那为什么还需要“应用上下文”对象呢?对于单应用单请求来说,使用“请求上下文”确实就可以了。然而,Flask的设计理念之一就是多应用的支持。当在一个应用的请求上下文环境中,需要嵌套处理另一个应用的相关操作时,“请求上下文”显然就不能很好地解决问题了。如何让请求找到“正确”的应用呢?我们可能会想到,可以再增加一个请求上下文环境,并将其推入_request_ctx_stack栈中。由于两个上下文环境的运行是独立的,不会相互干扰,所以通过调用_request_ctx_stack.top.app或者魔法current_app也可以获得当前上下文环境正在处理哪个应用。这种办法在一定程度上可行,但是如果对于第二个应用的处理不涉及到相关请求,那也就无从谈起“请求上下文”。

为了应对这个问题,Flask中将应用相关的信息单独拿出来,形成一个“应用上下文”对象。这个对象可以和“请求上下文”一起使用,也可以单独拿出来使用。不过有一点需要注意的是:在创建“请求上下文”时一定要创建一个“应用上下文”对象。有了“应用上下文”对象,便可以很容易地确定当前处理哪个应用,这就是魔法current_app。在0.1版本中,current_app是对_request_ctx_stack.top.app的引用,而在0.9版本中current_app是对_app_ctx_stack.top.app的引用。

下面以一个多应用的例子进行说明:

# example - Flask v0.9  >>> from flask import Flask, _request_ctx_stack, _app_ctx_stack  # 创建两个Flask应用  >>> app = Flask(__name__)  >>> app2 = Flask(__name__)  # 先查看两个栈中的内容  >>> _request_ctx_stack._local.__storage__  {}  >>> _app_ctx_stack._local.__storage__  {}  # 构建一个app的请求上下文环境,在这个环境中运行app2的相关操作  >>> with app.test_request_context():          print "Enter app's Request Context:"          print _request_ctx_stack._local.__storage__          print _app_ctx_stack._local.__storage__          print          with app2.app_context():              print "Enter app2's App Context:"              print _request_ctx_stack._local.__storage__              print _app_ctx_stack._local.__storage__              print              # do something          print "Exit app2's App Context:"          print _request_ctx_stack._local.__storage__          print _app_ctx_stack._local.__storage__          print  # Result  Enter app's Request Context:  {<greenlet.greenlet object at 0x000000000727A178>: {'stack': [<RequestContext 'http://localhost/' [GET] of __main__>]}}  {<greenlet.greenlet object at 0x000000000727A178>: {'stack': [<flask.ctx.AppContext object at 0x0000000005DD0DD8>]}}     Enter app2's App Context:  {<greenlet.greenlet object at 0x000000000727A178>: {'stack': [<RequestContext 'http://localhost/' [GET] of __main__>]}}  {<greenlet.greenlet object at 0x000000000727A178>: {'stack': [<flask.ctx.AppContext object at 0x0000000005DD0DD8>, <flask.ctx.AppContext object at 0x0000000007313198>]}}     Exit app2's App Context  {<greenlet.greenlet object at 0x000000000727A178>: {'stack': [<RequestContext 'http://localhost/' [GET] of __main__>]}}  {<greenlet.greenlet object at 0x000000000727A178>: {'stack': [<flask.ctx.AppContext object at 0x0000000005DD0DD8>]}}

在以上的例子中:

  • 我们首先创建了两个Flask应用app和app2;

  • 接着我们构建了一个app的请求上下文环境。当进入这个环境中时,这时查看两个栈的内容,发现两个栈中已经有了当前请求的请求上下文对象和应用上下文对象。并且栈顶的元素都是app的请求上下文和应用上下文;

  • 之后,我们再在这个环境中嵌套app2的应用上下文。当进入app2的应用上下文环境时,两个上下文环境便隔离开来,此时再查看两个栈的内容,发现_app_ctx_stack中推入了app2的应用上下文对象,并且栈顶指向它。这时在app2的应用上下文环境中,current_app便会一直指向app2;

  • 当离开app2的应用上下文环境,_app_ctx_stack栈便会销毁app2的应用上下文对象。这时查看两个栈的内容,发现两个栈中只有app的请求的请求上下文对象和应用上下文对象。

  • 最后,离开app的请求上下文环境后,两个栈便会销毁app的请求的请求上下文对象和应用上下文对象,栈为空。

与上下文对象有关的“全局变量”

在Flask中,为了更加方便地处理一些变量,特地提出了“全局变量”的概念。这些全局变量有:

# Flask v0.9  _request_ctx_stack = LocalStack()  _app_ctx_stack = LocalStack()  current_app = LocalProxy(_find_app)  request = LocalProxy(partial(_lookup_object, 'request'))  session = LocalProxy(partial(_lookup_object, 'session'))  g = LocalProxy(partial(_lookup_object, 'g'))     # 辅助函数  def _lookup_object(name):      top = _request_ctx_stack.top      if top is None:          raise RuntimeError('working outside of request context')      return getattr(top, name)        def _find_app():      top = _app_ctx_stack.top      if top is None:          raise RuntimeError('working outside of application context')      return top.app

可以看出,Flask中使用的一些“全局变量”,包括current_app、request、session、g等都来自于上下文对象。其中current_app一直指向_app_ctx_stack栈顶的“应用上下文”对象,是对当前应用的引用。而request、session、g等一直指向_request_ctx_stack栈顶的“请求上下文”对象,分别引用请求上下文的request、session和g。不过,从  Flask 0.10 起,对象 g 存储在应用上下文中而不再是请求上下文中。

另外一个问题,在形成这些“全局变量”的时候,使用了werkzeug.local模块的LocalProxy类。之所以要用该类,主要是为了动态地实现对栈顶元素的引用。如果不使用这个类,在生成上述“全局变量”的时候,它们因为指向栈顶元素,而栈顶元素此时为None,所以这些变量也会被设置为None常量。后续即使有上下文对象被推入栈中,相应的“全局变量”也不会发生改变。为了动态地实现对栈顶元素的引用,这里必须使用werkzeug.local模块的LocalProxy类。

关于Flask中的请求上下文和应用上下文对象如何理解就分享到这里了,希望以上内容可以对大家有一定的帮助,可以学到更多知识。如果觉得文章不错,可以把它分享出去让更多的人看到。

--结束END--

本文标题: Flask中的请求上下文和应用上下文对象如何理解

本文链接: https://www.lsjlt.com/news/287054.html(转载时请注明来源链接)

有问题或投稿请发送至: 邮箱/279061341@qq.com    QQ/279061341

本篇文章演示代码以及资料文档资料下载

下载Word文档到电脑,方便收藏和打印~

下载Word文档
猜你喜欢
  • Flask中的请求上下文和应用上下文对象如何理解
    这篇文章将为大家详细讲解有关Flask中的请求上下文和应用上下文对象如何理解,文章内容质量较高,因此小编分享给大家做个参考,希望大家阅读完这篇文章后对相关知识有一定的了解。在Flask中处理请求时,应用会生成一个“请求上下文”对象。整个请求...
    99+
    2023-06-17
  • Flask的上下文管理详解
    本篇内容介绍了“Flask的上下文管理详解”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!Flask线程间上下文安全Falsk完成线程安全的原...
    99+
    2023-06-02
  • Flask请求钩子与上下文及异常处理分项精解
    目录一、请求钩子学习介绍二、上下文1.介绍2.请求上下文3.应用上下文4.G对象三、异常处理1.HTTP异常主动抛出2.捕获错误一、请求钩子学习 介绍 1.为了让每个视图函数避免编写...
    99+
    2024-04-02
  • Springboot 如何获取上下文对象
    目录Springboot上下文对象获取或者更简单的写法:spring boot获取上下文 随时取出被spring管理的bean对象方法一:方式二:Springboot上下文对象获取 ...
    99+
    2024-04-02
  • 基于 Hyperf ,进行便捷的上下文和协程调度管理,实现 伪事务 般的defer应用和请求级上下文管理
    hyperf Hyperf go Coroutine defer 场景 一个API项目,日常写代码过程中,在需要进行上下文设置时,当然是字面意思,但有时候,一个API动作的完成,可能需要有一些主...
    99+
    2023-10-09
    数据库 php swoole
  • 如何在 google cloud run for firebase 中创建上下文对象
    积累知识,胜过积蓄金银!毕竟在Golang开发的过程中,会遇到各种各样的问题,往往都是一些细节知识点还没有掌握好而导致的,因此基础知识点的积累是很重要的。下面本文《如何在 google cloud ...
    99+
    2024-04-05
  • 如何理解Linux的CPU上下文切换
    今天就跟大家聊聊有关如何理解Linux的CPU上下文切换,可能很多人都不太了解,为了让大家更加了解,小编给大家总结了以下内容,希望大家根据这篇文章可以有所收获。如何理解Linux的上下文切换Linux 是一个多任务操作系统,它支持同时运行的...
    99+
    2023-06-16
  • Blob对象如何实现文件上传下载功能
    本篇内容介绍了“Blob对象如何实现文件上传下载功能”的有关知识,在实际案例的操作过程中,不少人都会遇到这样的困境,接下来就让小编带领大家学习一下如何处理这些情况吧!希望大家仔细阅读,能够学有所成!什么是Blod?Blob 对象表示一个不可...
    99+
    2023-07-04
  • 如何利用上下文属性将 C++ 对象嵌入 QML 里
    本篇文章为大家展示了如何利用上下文属性将 C++ 对象嵌入 QML 里,内容简明扼要并且容易理解,绝对能使你眼前一亮,通过这篇文章的详细介绍希望你能有所收获。一、设置简单的上下文属性例如,这里有一个 ...
    99+
    2023-06-22
  • 如何在python中使用上下文管理器
    如何在python中使用上下文管理器?相信很多没有经验的人对此束手无策,为此本文总结了问题出现的原因和解决方法,通过这篇文章希望你能解决这个问题。Python的优点有哪些1、简单易用,与C/C++、Java、C# 等传统语言相比,Pytho...
    99+
    2023-06-14
  • 如何访问上下文中的键
    Golang小白一枚,正在不断学习积累知识,现将学习到的知识记录一下,也是将我的所得分享给大家!而今天这篇文章《如何访问上下文中的键》带大家来了解一下##content_title##,希望对大家的...
    99+
    2024-04-05
  • JavaScript中如何执行上下文和堆栈
    小编给大家分享一下JavaScript中如何执行上下文和堆栈,相信大部分人都还不怎么了解,因此分享这篇文章给大家参考一下,希望大家阅读完这篇文章后大有收获,下面让我们一起去了解一下吧!什么是执行上下文?Ja...
    99+
    2024-04-02
  • 详解Python中的上下文管理器原理
    目录with语句上下文管理器原理自定义上下文管理器contextmanager 装饰器with语句 在我们日常使用场景中,经常会操作一些资源,比如文件对象、数据库连接、Socket连...
    99+
    2023-03-11
    Python上下文管理器原理 Python上下文管理器使用 Python上下文管理器
  • SpringBoot上传和下载文件的原理解析
    技术概述 我们的项目是实现一个论坛。在论坛上发布博客时应该要可以上传文件,用户阅读博客是应该要可以下载文件。于是我去学习了SpringBoot的上传和下载文件,我感觉技术的难点在于使...
    99+
    2024-04-02
  • 详解在SpringBoot应用中获取应用上下文方法
    定义上下文工具类:package com.alimama.config;import org.springframework.context.ApplicationContext;public class SpringContextUtil...
    99+
    2023-05-31
    spring boot 上下文
  • 详解Python中的with语句和上下文管理器
    目录一、with语句的使用二、上下文管理器三、小结如果你有阅读源码的习惯,可能会看到一些优秀的代码经常出现带有 with 关键字的语句,它通常用在什么场景呢?对于系统资源如文件、数据...
    99+
    2024-04-02
  • 小程序如何创建并返回map上下文mapContext对象
    本文将为大家详细介绍“小程序如何创建并返回map上下文mapContext对象”,内容步骤清晰详细,细节处理妥当,而小编每天都会更新不同的知识点,希望这篇“小程序如何创建并返回map上下文mapContext对象”能够给你意想不到的收获,请...
    99+
    2023-06-26
  • Java如何使用Sftp和Ftp实现对文件的上传和下载
    这篇文章将为大家详细讲解有关Java如何使用Sftp和Ftp实现对文件的上传和下载,小编觉得挺实用的,因此分享给大家做个参考,希望大家阅读完这篇文章后可以有所收获。第一步,导入maven依赖<!-- FTP依赖包 ...
    99+
    2023-06-14
  • 如何在PHP开发中处理文件上传和下载?
    如何在PHP开发中处理文件上传和下载?文件上传和下载是Web应用程序中常见的功能之一。在PHP开发中,处理文件上传和下载是相对简单的,只需使用PHP提供的内置函数和特定的文件操作函数。本文将详细介绍如何在PHP开发中处理文件上传和下载的方法...
    99+
    2023-11-02
    文件上传 文件下载 PHP开发
  • 如何处理PHP开发中的文件上传和下载问题
    在PHP开发中,文件上传和下载是常见的功能需求。本文将介绍如何处理PHP开发中的文件上传和下载问题,并提供具体的代码示例,帮助读者快速上手。一、文件上传创建上传表单首先,需要在页面上创建一个上传表单,以便用户选择并上传文件。可以使用HTML...
    99+
    2023-10-21
    文件上传 文件下载 PHP开发
软考高级职称资格查询
编程网,编程工程师的家园,是目前国内优秀的开源技术社区之一,形成了由开源软件库、代码分享、资讯、协作翻译、讨论区和博客等几大频道内容,为IT开发者提供了一个发现、使用、并交流开源技术的平台。
  • 官方手机版

  • 微信公众号

  • 商务合作