API Request: Document Upload create only a Corrupt File within M-Files

Hello,

I am currently struggling with uploading documents to M-Files via the REST API. I am using a Laravel PHP application to create the request. From the technical side, the following works so far:
• Authentication
• Creating an UploadFile
• Creating a SingleFileDocument or MultiFileDocument

However, the file in M-Files has the correct filename and file type but is always just an empty container. The actual document content is never uploaded and the file is corrupt.

What am I missing?


UploadFileRequest

CreateSingleFileDocument

Best regards

Sebastian

  • What's the result of that initial request?  Can you show the raw HTTP request/response that this PHP causes?  My suspicion is that is somehow incorrect.

    Honestly, I know that you can submit multiple files via this but for a single file it's often easier to simply pass the file content up in the body.

  • Hey Craig

    Many thanks for your response.

    $requestUrl = $url. '/REST/files'
    $responseStatus = 200;

    array:5 [▼
      "UploadID" => 4
      "Title" => "m-files"
      "Extension" => "pdf"
      "Size" => 236874
      "TempFilePath" => ""
    ]

    The response status for the first request is always 200, and I assume it returns the file size, indicating that everything worked properly. In the second request, I attach the UploadID as documented, but the file somehow ends up being corrupted in the M-Files system.

    What would a request look like to directly send the file within the /REST/objects/0 request?

    Best regards

    Stan

  • The response of the second request is:

    {
    "Title":"m-files",
    "EscapedTitleWithID":"m-files (ID 247).pdf",
    "DisplayID":"247",
    "ObjVer":{
    "Version":3,
    "VersionType":4,
    "ID":247,
    "Type":0
    },
    "Class":207,
    "CheckedOutAtUtc":"1601-01-01T00:00:00Z",
    "CheckedOutAt":"1601-01-01T00:00:00Z",
    "LastModifiedUtc":"2024-11-22T13:21:27Z",
    "LastModified":"2024-11-22T13:21:27Z",
    "ObjectCheckedOut":false,
    "ObjectCheckedOutToThisUser":false,
    "CheckedOutTo":0,
    "SingleFile":true,
    "HasRelationshipsFrom":false,
    "HasRelationshipsTo":false,
    "HasRelationshipsFromThis":false,
    "HasRelationshipsToThis":false,
    "HasAssignments":false,
    "Deleted":false,
    "IsStub":false,
    "ThisVersionLatestToThisUser":true,
    "CreatedUtc":"2024-11-22T13:21:22Z",
    "Created":"2024-11-22T13:21:22Z",
    "Files":[
    {
    "Name":"m-files",
    "EscapedName":"m-files.pdf",
    "Extension":"pdf",
    "Size":236874,
    "LastModified":"2024-11-22T13:21:24Z",
    "ChangeTimeUtc":"2024-11-22T13:21:24Z",
    "ChangeTime":"2024-11-22T13:21:24Z",
    "CreatedUtc":"2024-11-22T13:21:22Z",
    "CreatedDisplayValue":"22.11.2024 13:21",
    "LastModifiedDisplayValue":"22.11.2024 13:21",
    "FileGUID":"{424128F4-FF05-4E00-A84E-54A8E4088F44}",
    "ID":280,
    "Version":1,
    "FileVersionType":3
    }
    ],
    "VisibleAfterOperation":true,
    "PathInIDView":"0\\0-999\\247\\S\\v3",
    "LastModifiedDisplayValue":"22.11.2024 13:21",
    "CheckedOutAtDisplayValue":"01.01.1601 00:00",
    "CreatedDisplayValue":"22.11.2024 13:21",
    "ObjectVersionFlags":2,
    "Score":0,
    "LastAccessedByMe":"2024-11-22T13:21:25Z",
    "AccessedByMeUtc":"2024-11-22T13:21:25Z",
    "AccessedByMe":"2024-11-22T13:21:25Z",
    "ObjectGUID":"{DA93DAF1-C28E-4B75-BEA8-B77A3B39DC64}",
    "ObjectCapabilityFlags":-1,
    "ObjectFlags":68,
    "propertyID":0,
    "LatestCheckedInVersion":3,
    "BaseProperties":[
    
    ]
    }

  • 1st Request

    Illuminate\Http\Client\Request {#2819
      #request: GuzzleHttp\Psr7\Request {#2813
        -method: "POST"
        -requestTarget: null
        -uri: GuzzleHttp\Psr7\Uri {#2797
          -scheme: "https"
          -userInfo: ""
          -host: "removed"
          -port: null
          -path: "/REST/files"
          -query: ""
          -fragment: ""
          -composedComponents: null
        }
        -headers: array:5 [
          "Content-Length" => array:1 [
            0 => "13363"
          ]
          "User-Agent" => array:1 [
            0 => "GuzzleHttp/7"
          ]
          "Content-Type" => array:1 [
            0 => "multipart/form-data; boundary=7159ea7915683418715291485aa0c22c28f0e27a"
          ]
          "Host" => array:1 [
            0 => "URL_ REMOVED"
          ]
          "X-Authentication" => array:1 [
            0 => "TOKEN_ REMOVED REMOVED"
          ]
        ]
        -headerNames: array:5 [
          "content-length" => "Content-Length"
          "user-agent" => "User-Agent"
          "content-type" => "Content-Type"
          "host" => "Host"
          "x-authentication" => "X-Authentication"
        ]
        -protocol: "1.1"
        -stream: GuzzleHttp\Psr7\MultipartStream {#2799
          -boundary: "7159ea7915683418715291485aa0c22c28f0e27a"
          -stream: GuzzleHttp\Psr7\AppendStream {#2800
            -streams: array:4 [
              0 => GuzzleHttp\Psr7\Stream {#2802
                -stream: stream resource {@1583
                  wrapper_type: "PHP"
                  stream_type: "TEMP"
                  mode: "w+b"
                  unread_bytes: 0
                  seekable: true
                  uri: "php://temp"
                  options: []
                }
                -size: 223
                -seekable: true
                -readable: true
                -writable: true
                -uri: "php://temp"
                -customMetadata: []
              }
              1 => GuzzleHttp\Psr7\Stream {#2801
                -stream: stream resource {@1579
                  wrapper_type: "PHP"
                  stream_type: "TEMP"
                  mode: "w+b"
                  unread_bytes: 0
                  seekable: true
                  uri: "php://temp"
                  options: []
                }
                -size: 13092
                -seekable: true
                -readable: true
                -writable: true
                -uri: "php://temp"
                -customMetadata: []
              }
              2 => GuzzleHttp\Psr7\Stream {#2803
                -stream: stream resource {@1585
                  wrapper_type: "PHP"
                  stream_type: "TEMP"
                  mode: "w+b"
                  unread_bytes: 0
                  seekable: true
                  uri: "php://temp"
                  options: []
                }
                -size: 2
                -seekable: true
                -readable: true
                -writable: true
                -uri: "php://temp"
                -customMetadata: []
              }
              3 => GuzzleHttp\Psr7\Stream {#2804
                -stream: stream resource {@1587
                  wrapper_type: "PHP"
                  stream_type: "TEMP"
                  mode: "w+b"
                  unread_bytes: 0
                  seekable: true
                  uri: "php://temp"
                  options: []
                }
                -size: 46
                -seekable: true
                -readable: true
                -writable: true
                -uri: "php://temp"
                -customMetadata: []
              }
            ]
            -seekable: true
            -current: 0
            -pos: 0
          }
        }
      }
      #data: array:1 [
        0 => array:3 [
          "name" => "file"
          "contents" => "REMOVED_TOO_LARGE"
          "filename" => "test.docx"
        ]
      ]
    } // vendor/laravel/framework/src/Illuminate/Http/Client/PendingRequest.php:1290
    array:13 [
      "connect_timeout" => 10
      "crypto_method" => 33
      "http_errors" => false
      "timeout" => 30
      "laravel_data" => array:1 [
        0 => array:3 [
          "name" => "file"
          "contents" => "REMOVED_TOO_LARGE"
          "filename" => "test.docx"
        ]
      ]
      "on_stats" => Closure($transferStats) {#1467
        class: "Illuminate\Http\Client\PendingRequest"
        this: Illuminate\Http\Client\PendingRequest {#2505 …}
      }
      "synchronous" => true
      "handler" => GuzzleHttp\HandlerStack {#1705
        -handler: Closure(RequestInterface $request, array $options): PromiseInterface {#1053
          returnType: "GuzzleHttp\Promise\PromiseInterface"
          class: "GuzzleHttp\Handler\Proxy"
          use: {
            $default: Closure(RequestInterface $request, array $options): PromiseInterface {#2781 …}
            $streaming: GuzzleHttp\Handler\StreamHandler {#2782 …}
          }
        }
        -stack: array:7 [
          0 => array:2 [
            0 => Closure(callable $handler): callable {#2772
              returnType: "callable"
              class: "GuzzleHttp\Middleware"
              use: {
                $bodySummarizer: null
              }
            }
            1 => "http_errors"
          ]
          1 => array:2 [
            0 => Closure(callable $handler): RedirectMiddleware {#2786
              returnType: "GuzzleHttp\RedirectMiddleware"
              class: "GuzzleHttp\Middleware"
            }
            1 => "allow_redirects"
          ]
          2 => array:2 [
            0 => Closure(callable $handler): callable {#2790
              returnType: "callable"
              class: "GuzzleHttp\Middleware"
            }
            1 => "cookies"
          ]
          3 => array:2 [
            0 => Closure(callable $handler): PrepareBodyMiddleware {#2791
              returnType: "GuzzleHttp\PrepareBodyMiddleware"
              class: "GuzzleHttp\Middleware"
            }
            1 => "prepare_body"
          ]
          4 => array:2 [
            0 => Closure($handler) {#2793
              class: "Illuminate\Http\Client\PendingRequest"
              this: Illuminate\Http\Client\PendingRequest {#2505 …}
            }
            1 => ""
          ]
          5 => array:2 [
            0 => Closure($handler) {#2795
              class: "Illuminate\Http\Client\PendingRequest"
              this: Illuminate\Http\Client\PendingRequest {#2505 …}
            }
            1 => ""
          ]
          6 => array:2 [
            0 => Closure($handler) {#2794
              class: "Illuminate\Http\Client\PendingRequest"
              this: Illuminate\Http\Client\PendingRequest {#2505 …}
            }
            1 => ""
          ]
        ]
        -cached: Closure($request, array $options) {#2812
          class: "GuzzleHttp\Middleware"
          use: {
            $handler: GuzzleHttp\RedirectMiddleware {#2811 …}
            $bodySummarizer: null
          }
        }
      }
      "cookies" => GuzzleHttp\Cookie\CookieJar {#2796
        -cookies: []
        -strictMode: false
      }
      "allow_redirects" => array:5 [
        "max" => 5
        "protocols" => array:2 [
          0 => "http"
          1 => "https"
        ]
        "strict" => false
        "referer" => false
        "track_redirects" => false
      ]
      "decode_content" => true
      "verify" => true
      "idn_conversion" => false
      ] // vendor/laravel/framework/src/Illuminate/Http/Client/PendingRequest.php:1290

    2nd Request

    Illuminate\Http\Client\Request {#2841
      #request: GuzzleHttp\Psr7\Request {#2835
        -method: "POST"
        -requestTarget: null
        -uri: GuzzleHttp\Psr7\Uri {#2826
          -scheme: "https"
          -userInfo: ""
          -host: "REMOVED"
          -port: null
          -path: "/REST/objects/0"
          -query: ""
          -fragment: ""
          -composedComponents: null
        }
        -headers: array:5 [
          "Content-Length" => array:1 [
            0 => "627"
          ]
          "User-Agent" => array:1 [
            0 => "GuzzleHttp/7"
          ]
          "Host" => array:1 [
            0 => "REMOVED_URL"
          ]
          "X-Authentication" => array:1 [
            0 => "REMOVED"
          ]
          "Content-Type" => array:1 [
            0 => "application/json"
          ]
        ]
        -headerNames: array:5 [
          "content-length" => "Content-Length"
          "user-agent" => "User-Agent"
          "host" => "Host"
          "x-authentication" => "X-Authentication"
          "content-type" => "Content-Type"
        ]
        -protocol: "1.1"
        -stream: GuzzleHttp\Psr7\Stream {#2828
          -stream: stream resource {@1612
            wrapper_type: "PHP"
            stream_type: "TEMP"
            mode: "w+b"
            unread_bytes: 0
            seekable: true
            uri: "php://temp"
            options: []
          }
          -size: 627
          -seekable: true
          -readable: true
          -writable: true
          -uri: "php://temp"
          -customMetadata: []
        }
      }
      #data: array:2 [
        "PropertyValues" => array:7 [
          0 => array:2 [
            "PropertyDef" => 0
            "TypedValue" => array:2 [
              "DataType" => 1
              "Value" => "test"
            ]
          ]
          1 => array:2 [
            "PropertyDef" => 22
            "TypedValue" => array:2 [
              "DataType" => 8
              "Value" => true
            ]
          ]
          2 => array:2 [
            "PropertyDef" => 1275
            "TypedValue" => array:2 [
              "DataType" => 10
              "Lookups" => array:1 [
                0 => array:1 [
                  "Item" => 100
                ]
              ]
            ]
          ]
          3 => array:2 [
            "PropertyDef" => 1301
            "TypedValue" => array:2 [
              "DataType" => 10
              "Lookups" => array:1 [
                0 => array:1 [
                  "Item" => 30
                ]
              ]
            ]
          ]
          4 => array:2 [
            "PropertyDef" => 100
            "TypedValue" => array:2 [
              "DataType" => 9
              "Lookup" => array:2 [
                "Item" => 207
                "Version" => -1
              ]
            ]
          ]
          5 => array:2 [
            "PropertyDef" => 38
            "TypedValue" => array:2 [
              "DataType" => 9
              "Lookup" => array:2 [
                "Item" => 121
                "Version" => -1
              ]
            ]
          ]
          6 => array:2 [
            "PropertyDef" => 39
            "TypedValue" => array:2 [
              "DataType" => 9
              "Lookup" => array:2 [
                "Item" => 217
                "Version" => -1
              ]
            ]
          ]
        ]
        "Files" => array:1 [
          0 => array:5 [
            "UploadID" => 8
            "Title" => "test"
            "Extension" => "docx"
            "Size" => 13092
            "TempFilePath" => ""
          ]
        ]
      ]
    } // vendor/laravel/framework/src/Illuminate/Http/Client/PendingRequest.php:1290
    array:13 [
      "connect_timeout" => 10
      "crypto_method" => 33
      "http_errors" => false
      "timeout" => 30
      "laravel_data" => array:2 [
        "PropertyValues" => array:7 [
          0 => array:2 [
            "PropertyDef" => 0
            "TypedValue" => array:2 [
              "DataType" => 1
              "Value" => "test"
            ]
          ]
          1 => array:2 [
            "PropertyDef" => 22
            "TypedValue" => array:2 [
              "DataType" => 8
              "Value" => true
            ]
          ]
          2 => array:2 [
            "PropertyDef" => 1275
            "TypedValue" => array:2 [
              "DataType" => 10
              "Lookups" => array:1 [
                0 => array:1 [
                  "Item" => 100
                ]
              ]
            ]
          ]
          3 => array:2 [
            "PropertyDef" => 1301
            "TypedValue" => array:2 [
              "DataType" => 10
              "Lookups" => array:1 [
                0 => array:1 [
                  "Item" => 30
                ]
              ]
            ]
          ]
          4 => array:2 [
            "PropertyDef" => 100
            "TypedValue" => array:2 [
              "DataType" => 9
              "Lookup" => array:2 [
                "Item" => 207
                "Version" => -1
              ]
            ]
          ]
          5 => array:2 [
            "PropertyDef" => 38
            "TypedValue" => array:2 [
              "DataType" => 9
              "Lookup" => array:2 [
                "Item" => 121
                "Version" => -1
              ]
            ]
          ]
          6 => array:2 [
            "PropertyDef" => 39
            "TypedValue" => array:2 [
              "DataType" => 9
              "Lookup" => array:2 [
                "Item" => 217
                "Version" => -1
              ]
            ]
          ]
        ]
        "Files" => array:1 [
          0 => array:5 [
            "UploadID" => 8
            "Title" => "test"
            "Extension" => "docx"
            "Size" => 13092
            "TempFilePath" => ""
          ]
        ]
      ]
      "on_stats" => Closure($transferStats) {#2807
        class: "Illuminate\Http\Client\PendingRequest"
        this: Illuminate\Http\Client\PendingRequest {#2556 …}
      }
      "synchronous" => true
      "handler" => GuzzleHttp\HandlerStack {#2804
        -handler: Closure(RequestInterface $request, array $options): PromiseInterface {#1705
          returnType: "GuzzleHttp\Promise\PromiseInterface"
          class: "GuzzleHttp\Handler\Proxy"
          use: {
            $default: Closure(RequestInterface $request, array $options): PromiseInterface {#2787 …}
            $streaming: GuzzleHttp\Handler\StreamHandler {#2818 …}
          }
        }
        -stack: array:7 [
          0 => array:2 [
            0 => Closure(callable $handler): callable {#2793
              returnType: "callable"
              class: "GuzzleHttp\Middleware"
              use: {
                $bodySummarizer: null
              }
            }
            1 => "http_errors"
          ]
          1 => array:2 [
            0 => Closure(callable $handler): RedirectMiddleware {#2794
              returnType: "GuzzleHttp\RedirectMiddleware"
              class: "GuzzleHttp\Middleware"
            }
            1 => "allow_redirects"
          ]
          2 => array:2 [
            0 => Closure(callable $handler): callable {#2792
              returnType: "callable"
              class: "GuzzleHttp\Middleware"
            }
            1 => "cookies"
          ]
          3 => array:2 [
            0 => Closure(callable $handler): PrepareBodyMiddleware {#2777
              returnType: "GuzzleHttp\PrepareBodyMiddleware"
              class: "GuzzleHttp\Middleware"
            }
            1 => "prepare_body"
          ]
          4 => array:2 [
            0 => Closure($handler) {#2772
              class: "Illuminate\Http\Client\PendingRequest"
              this: Illuminate\Http\Client\PendingRequest {#2556 …}
            }
            1 => ""
          ]
          5 => array:2 [
            0 => Closure($handler) {#2823
              class: "Illuminate\Http\Client\PendingRequest"
              this: Illuminate\Http\Client\PendingRequest {#2556 …}
            }
            1 => ""
          ]
          6 => array:2 [
            0 => Closure($handler) {#2825
              class: "Illuminate\Http\Client\PendingRequest"
              this: Illuminate\Http\Client\PendingRequest {#2556 …}
            }
            1 => ""
          ]
        ]
        -cached: Closure($request, array $options) {#2834
          class: "GuzzleHttp\Middleware"
          use: {
            $handler: GuzzleHttp\RedirectMiddleware {#2833 …}
            $bodySummarizer: null
          }
        }
      }
      "cookies" => GuzzleHttp\Cookie\CookieJar {#2813
        -cookies: []
        -strictMode: false
      }
      "allow_redirects" => array:5 [
        "max" => 5
        "protocols" => array:2 [
          0 => "http"
          1 => "https"
        ]
        "strict" => false
        "referer" => false
        "track_redirects" => false
      ]
      "decode_content" => true
      "verify" => true
      "idn_conversion" => false
    ] // vendor/laravel/framework/src/Illuminate/Http/Client/PendingRequest.php:1290

  • I'm not sure I understood all of that (I was hoping for just the raw request, but it has a lot more information there which I'm parsing).  It looks like it stored *something*, but that the something was wrong.  The response of the second request seems to indicate a 236k file, but the total content length specified in the first request was 12k...  That's not right.

    I'd really like to see the actual raw HTTP request for the first request.  My suspicion is that it's the multipart form data which is causing an issue.  Can you alter it to use the application/octet-stream version at M-Files Web Service: Temporary upload (where the request body simply contains a single file content)?

  • Hi Craig

    Thank you very much for your reply.

    I did some additional research on sending such requests and came across a suggestion on Stack Overflow to add the name “file” when attaching the file content. This seemed to resolve the issue of a corrupt file in M-Files.



    Many thanks for your help!

    Best regrads

    Sebastian