diff --git a/CHANGES.rst b/CHANGES.rst
index 0a3cd08e0..9665d0317 100644
--- a/CHANGES.rst
+++ b/CHANGES.rst
@@ -10,6 +10,9 @@ https://github.com/zopefoundation/Zope/blob/4.x/CHANGES.rst
 5.8.7 (unreleased)
 ------------------
 
+- Support form data in ``PUT`` requests (following the ``multipart`` example).
+  Fixes `#1182 <https://github.com/zopefoundation/Zope/issues/1182>`_.
+
 - Separate ZODB connection information into new ZODB Connections view.
 
 - Move the cache detail links to the individual database pages.
diff --git a/src/ZPublisher/HTTPRequest.py b/src/ZPublisher/HTTPRequest.py
index 20421a14b..9a497839e 100644
--- a/src/ZPublisher/HTTPRequest.py
+++ b/src/ZPublisher/HTTPRequest.py
@@ -1432,19 +1432,30 @@ class ZopeFieldStorage(ValueAccessor):
         url_qs = environ.get("QUERY_STRING", "")
         post_qs = ""
         hl = []
-        content_type = environ.get("CONTENT_TYPE",
-                                   "application/x-www-form-urlencoded")
-        hl.append(("content-type", content_type))
+        content_type = environ.get("CONTENT_TYPE")
+        if content_type is not None:
+            hl.append(("content-type", content_type))
+        else:
+            content_type = ""
         content_type, options = parse_options_header(content_type)
         content_type = content_type.lower()
         content_disposition = environ.get("CONTENT_DISPOSITION")
         if content_disposition is not None:
             hl.append(("content-disposition", content_disposition))
+        # Note: ``headers`` does not reflect the complete headers.
+        #  Likely, it should get removed altogether and accesses be replaced
+        #  by a lookup of the corresponding CGI environment keys.
         self.headers = Headers(hl)
         parts = ()
-        if method == "POST" \
-           and content_type in \
-           ("multipart/form-data", "application/x-www-form-urlencoded"):
+        if method in ("POST", "PUT") \
+           and content_type in (
+           "multipart/form-data", "application/x-www-form-urlencoded",
+           "application/x-url-encoded",
+           # ``Testing`` assumes "application/x-www-form-urlencoded"
+           # as default content type
+           # We have mapped a missing content type to ``""``.
+           "",
+           ):
             try:
                 fpos = fp.tell()
             except Exception:
@@ -1456,7 +1467,7 @@ class ZopeFieldStorage(ValueAccessor):
                     disk_limit=FORM_DISK_LIMIT,
                     memfile_limit=FORM_MEMFILE_LIMIT,
                     charset="latin-1").parts()
-            elif content_type == "application/x-www-form-urlencoded":
+            else:
                 post_qs = fp.read(FORM_MEMORY_LIMIT).decode("latin-1")
                 if fp.read(1):
                     raise BadRequest("form data processing "

diff --git a/src/ZPublisher/tests/testHTTPRequest.py b/src/ZPublisher/tests/testHTTPRequest.py
index d7fe18e4d..7b1131779 100644
--- a/src/ZPublisher/tests/testHTTPRequest.py
+++ b/src/ZPublisher/tests/testHTTPRequest.py
@@ -1468,6 +1468,7 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
                 "SERVER_NAME": "localhost",
                 "SERVER_PORT": "8080",
                 "REQUEST_METHOD": "PUT",
+                "CONTENT_TYPE": "application",
             },
             None,
         )
@@ -1514,6 +1515,23 @@ class HTTPRequestTests(unittest.TestCase, HTTPRequestFactoryMixin):
         self.assertEqual(req["x"], "äöü")
         self.assertEqual(req["y"], "äöü")
 
+    def test_put_with_form(self):
+        req_factory = self._getTargetClass()
+        body = b"foo=foo"
+        req = req_factory(
+            BytesIO(body),
+            {
+                "SERVER_NAME": "localhost",
+                "SERVER_PORT": "8080",
+                "REQUEST_METHOD": "PUT",
+                "CONTENT_TYPE": "application/x-www-form-urlencoded",
+                "CONTENT_LENGTH": len(body),
+            },
+            None,
+        )
+        req.processInputs()
+        self.assertEqual(req.form["foo"], "foo")
+
 
 class TestHTTPRequestZope3Views(TestRequestViewsBase):
 

Clarification on  Handling Image Uploads via HTTP PUT in Zope5 with WSGI Server
### What I did:

I encountered an issue related to the handling of image uploads when using the HTTP PUT method in Zope5 with a WSGI server. Here are the steps I followed to reproduce the problem:

1. Using a Zope5 installation with the WSGI server.
2. Sending an HTTP PUT request to upload an image.
3. Observing that the image data is received in the request body as encoded data.

### What I expect to happen:

I expected that, similar to Zope4 with the ZServer, I would receive the image data as part of the form, and I would be able to access it as an object. This is the behavior I was accustomed to in Zope4.

### What actually happened:

In Zope5 with the WSGI server, when I use the HTTP PUT method to upload an image, the image data is received in the request body, and the body data is encoded. As a result, I am unable to access the image data as a file upload object, which is different from the behavior in Zope4.

### What version of Python and Zope/Addons I am using:

- Operating System: Windows/Linux
- Python Version: 3.10.9
- Zope Version: 5.8.3

This report aims to highlight the difference in behavior between Zope4 and Zope5 when using HTTP PUT for image uploads and to understand whether this is the expected behavior for PUT operations.

Additional Observation:
https://github.com/zopefoundation/Zope/blob/5.8.3/src/ZPublisher/HTTPRequest.py#L1425
If i include "PUT" condition here, it is working as expected

Thank you.

src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_put_with_form
src/ZPublisher/tests/testHTTPRequest.py::RecordTests::test__str__returns_native_string src/ZPublisher/tests/testHTTPRequest.py::RecordTests::test_copy src/ZPublisher/tests/testHTTPRequest.py::RecordTests::test_dict_methods src/ZPublisher/tests/testHTTPRequest.py::RecordTests::test_dict_special_methods src/ZPublisher/tests/testHTTPRequest.py::RecordTests::test_eq src/ZPublisher/tests/testHTTPRequest.py::RecordTests::test_repr src/ZPublisher/tests/testHTTPRequest.py::RecordTests::test_str src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test___bobo_traverse___raises src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test___str____password_field src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test__authUserPW_non_ascii src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test__authUserPW_simple src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test__authUserPW_with_embedded_colon src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test__str__returns_native_string src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_bytes_converter src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_clone_doesnt_re_clean_environ src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_clone_keeps_only_last_PARENT src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_clone_keeps_preserves__auth src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_clone_preserves_direct_interfaces src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_clone_preserves_request_subclass src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_clone_preserves_response_class src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_clone_updates_method_to_GET src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_close_removes_stdin_references src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_debug_in_qs_gets_form_var src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_debug_not_in_qs_still_gets_attr src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_debug_override_via_form_other src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_field_charset src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_form_charset src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_form_urlencoded src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_getClientAddr_one_trusted_proxy src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_getClientAddr_trusted_proxy_last src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_getClientAddr_trusted_proxy_no_REMOTE_ADDR src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_getClientAddr_wo_trusted_proxy src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_getHeader_case_insensitive src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_getHeader_exact src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_getHeader_literal_turns_off_case_normalization src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_getHeader_nonesuch src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_getHeader_nonesuch_with_default src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_getHeader_underscore_is_dash src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_getVirtualRoot src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_get_with_body_and_query_string_ignores_body src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_issue_1095 src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_locale_fallback src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_locale_in_qs src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_locale_property_accessor src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_locale_property_override_via_form_other src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_locale_semantics src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_method_GET src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_method_POST src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_no_docstring_on_instance src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_parses_json_cookies src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_BODY src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_BODY_unseekable src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_SOAP src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_SOAP_query_string src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_seekable_form_data src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_unseekable_form_data src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_unspecified_file src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_w_cookie_parsing src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_w_defaults src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_w_defaults_w_taints src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_w_dotted_name_as_tuple src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_w_large_input_gets_tempfile src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_w_marshalling_into_sequences src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_w_records_w_sequences src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_w_records_w_sequences_tainted src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_w_simple_containers src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_w_simple_containers_w_taints src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_w_simple_marshalling src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_w_simple_marshalling_w_taints src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_w_tainted_attribute_raises src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_w_tainted_values_cleans_exceptions src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_w_unicode_conversions src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_w_unicode_w_taints src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_w_urlencoded_and_qs src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_with_file_upload_gets_iterator src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_wo_marshalling src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_wo_marshalling_w_Taints src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_wo_query_string src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_xmlrpc src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_xmlrpc_controlled_allowed src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_xmlrpc_controlled_disallowed src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_xmlrpc_method src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_xmlrpc_query_string src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_processInputs_xmlrpc_with_args src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_put_with_body_and_query_string src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_put_with_body_limit src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_resolve_url_doesnt_send_endrequestevent src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_resolve_url_errorhandling src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_text__password_field src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_url_scheme src/ZPublisher/tests/testHTTPRequest.py::HTTPRequestTests::test_webdav_source_port_available src/ZPublisher/tests/testHTTPRequest.py::TestHTTPRequestZope3Views::test_no_traversal_of_view_request_attribute src/ZPublisher/tests/testHTTPRequest.py::TestSearchType::test_image_control src/ZPublisher/tests/testHTTPRequest.py::TestSearchType::test_leftmost src/ZPublisher/tests/testHTTPRequest.py::TestSearchType::test_special src/ZPublisher/tests/testHTTPRequest.py::TestSearchType::test_type