Files
File content does not travel in ordinary object messages. You download it in blocks through a download session, and you upload it either inline in the request that creates the object (up to 10 MiB) or in blocks through an upload session. Files belong to object versions; see Objects and versions.
Which method to use
| Task | Use |
|---|---|
| Read a file of an object version | DownloadFile_Begin, DownloadFile_ReadBlock in a loop, DownloadFile_Stop |
| Create a single-file document with a file of at most 10 MiB | AddObjectWithFiles with the content inline (OBJ_FILE_SOURCE_TYPE_FILE_CONTENT) |
| Create a document with a file of any size | UploadTempFile in blocks, UploadTempFileCommit, then AddObjectWithFiles with the upload ID (OBJ_FILE_SOURCE_TYPE_UPLOADED_FILE) |
DownloadFile, DownloadFileWithDownloadID, DownloadFileWithDownloadKey, GetFileDownloadUrl
and GetFileDownloadUrl2 of IRPCObjectOperations serve the mf-http-grpc gateway: over native
gRPC they answer "Not implemented.". The stateless upload services are described at the end of
this page.
The download guide and the
create-document guide show the calls in code.
Downloading
- Take the file's version from the object version:
ObjectVersion.files[]gives each file'sfile_ver(file ID and file version),title,extensionandsize. - Call
DownloadFile_Beginwithobj_file_ver(the object'sobj_idand the file'sfile_ver),format(FILE_FORMAT_NATIVEfor the file as stored), andprepare_file_for_downloading: true. Without that flag the server only checks access and records the access, and opens no download session. Setneed_checksum: trueto get the MD5 checksum infile_outline.md5_checksum. The response hasdownload_idandfile_outlinewith thesizeto expect. - Call
DownloadFile_ReadBlockwithdownload_id,offsetfrom 0 andblock_size(requestmin(block size, size - offset)each time) until you have readfile_outline.sizebytes. Do not read again after the last byte: the server has closed the download session.block_sizecan be at most 4 MiB (4 194 304 bytes); a larger value fails withE_INVALIDARG("Block size exceeded the limit of 4194304 bytes."). - Call
DownloadFile_Stopwith thedownload_id.
Verified with a 3 MiB file in 4 MiB blocks: the downloaded bytes and the server's MD5 matched the upload.
Your receive limit. A 4 MiB block plus framing is just over the 4 MiB default receive limit of
most gRPC libraries and fails on the client with RESOURCE_EXHAUSTED. Raise the limit, or read
smaller blocks such as 1 MiB. See Connecting.
Download sessions.
- A download ID is valid only in the session that opened it, and only on the server process that
opened it. On M-Files Cloud send the stickiness cookie
(Call metadata). From another session the ID answers
E_MFILES_NOT_FOUND("The specified download session 1 does not exist."). - When you read the file from start to end, the server closes the session as soon as you read the
last block; a later
ReadBlockanswers that the session does not exist.DownloadFile_Stopstill succeeds, so always call it: it releases the session when you stop early or read out of order. - The server closes download sessions that are left open: the timeout is 10 minutes by default.
Uploading inline
For small files, put the content in the creating request:
AddObjectWithFiles
object_type_id: 0
properties: [ class, name or title, ... ]
check_in: true
files: { type: OBJ_FILE_SOURCE_TYPE_FILE_CONTENT
data.file_content: { title: "report", extension: "pdf", file_data: <bytes> } }
Inline content works only for a single-file document (object type 0 with property 22, Single
file, true), needs a title, and is limited to 10 MiB (10 485 760 bytes); a larger file fails with
E_INVALIDARG ("The parameter is incorrect. (Inline file content: fileSize exceeds the maximum
allowed for inline content.)"), and so does inline content for a multi-file document. A 5 MiB file
was created this way. Use an upload session for anything else.
Uploading in blocks (upload sessions)
- Call
UploadTempFilewithupload_id: 0,total_size_in_bytes,offset: 0and the first block indata. Keep the returnedupload_id. - Send the next blocks with the same
upload_idand theiroffset. Make every block except the last a multiple of 4096 bytes; 1 MiB blocks work well. - Call
UploadTempFileCommitwithupload_idandlogical_size(the file size). Leavelow_digestandhigh_digest0. If the commit fails, the upload is gone: upload the file again. - Create the document with
AddObjectWithFilesandfiles: { type: OBJ_FILE_SOURCE_TYPE_UPLOADED_FILE, data.uploaded_file: { upload_id, title, extension, size } }.
Verified with a 3 MiB file in 1 MiB blocks; the new document's file had the expected size and MD5.
Upload sessions.
- An upload session works only in the session and on the server process that created it. On M-Files Cloud send the stickiness cookie on all its calls.
- It times out when idle (10 minutes by default). For a long upload, call
KeepUploadSessionAlive at least
every
session_data.keep_upload_session_alive_interval_in_seconds(300 seconds by default). - RemoveUploadSession discards an upload you no longer need.
- Each request is subject to the 48 MiB limit; a 49 MiB block fails with
RESOURCE_EXHAUSTED.
Stateless uploads (switched off by default)
IRPCFileTransfer (FileUploadBegin, FileUploadEnd,
FileUploadAttach) and the client-streaming
IRPCFileTransferStreaming (FileUploadWhole,
FileUploadBlock) upload without an upload session: the upload is identified by a file_ref.
In M-Files Server 26.11 this feature is switched off by default: every method of the two services
answers "Not implemented." (E_NOTIMPL), and the capability
ServerVaultCapabilities.file_upload_stateless_supported is false. Upload with
UploadTempFile and
UploadTempFileCommit as described
above, and use the stateless services only on a server that reports the capability.