www.gusucode.com > external 工具箱matlab源码程序 > external/interfaces/webservices/http/+matlab/+net/+http/MessageBody.m
classdef MessageBody %MessageBody The payload of an HTTP message % This object is contained in a RequestMessage or ResponseMessage. % % MessageBody properties: % % Data - the data prior to conversion to or after conversion from % a byte stream % ContentType - (read-only) the content type, if known % ContentCoding - (read-only) content-coding of the payload % Payload - the raw byte stream, if set or saved % % MessageBody methods: % % string, char - return the data as a string or character vector % show - return the data as a string with optional maximum length % % If you want to send a RequestMessage that contains data (which is usually % a PUT or POST request), you can set the Body property to your data or to a % MessageBody object containing your data. By default the data you specify % goes into the MessageBody.Data property. When you send a message % containing this data, MATLAB converts the data to a uint8 vector that is % the payload of the message sent to the server. Conversion of MATLAB data % to a payload depends on the type of the data and the Content-Type header % field you specify in the message (e.g., using a ContentTypeField). If you % do not specify a content type, MATLAB heuristically tries to deduce the % content type and creates a ContentTypeField naming that type. These % conversions are described for the Data property below. % % If you want to send a uint8 vector without any conversion, regardless % of the value of the ContentTypeField, set Payload instead of Data. % % In a ResponseMessage that contains a payload, the Body.Data property % contains the payload, converted to MATLAB data, based on the Content-Type % specified by the server in the response message. These conversions are % described for the Data property below. % % Normally, either the Data or Payload is set, but not both. If you % explicitly set one, the other is cleared, and requests and responses have % only Data set. But if you specify HTTPOptions.SavePayload, messages % returned by RequestMessage.send, as well as messages stored in the % returned LogRecords, will have both Data and Payload set, where Payload % represents the uint8 vector sent to or received from the server, and Data % is the MATLAB data. % % Also, both Data and Payload may both be set in the message returned by % RequestMessage.complete, and in HTTPException.Request when there was an % exception communicating with the server or converting the data. % % See also RequestMessage.Body, RequestMessage.send, % RequestMessage.complete, ResponseMessage, HTTPOptions, LogRecord % Copyrite 2015-2016 The MathWorks, Inc. properties (Dependent) % Data - The payload of the message in the form of MATLAB data % In a RequestMessage, this is the MATLAB data prior to any conversion to a % uint8 payload, and in a ResponseMessage, this is MATLAB data after % conversion from a uint8 payload. Data may be of multiple types. % % In a RequestMessage, conversion of Data to a payload depends happens when % you call RequestMessage.send or RequestMessage.complete. This conversion % depends on the Content-Type you specify in the message and the type of % Data. If you do not specify a Content-Type, the send and complete methods % try to deduce the type from the data and add the appropriate % ContentTypeField to the RequestMessage. % % In a ResponseMessage, the Data represents the payload converted to a % MATLAB type based on the Content-Type specified by the server in the % ResponseMessage. % % Output Conversion for RequestMessage % ------------------------------------ % % The following explains how Data is converted to a payload in a % RequestMessage based on the type/subtype and charset that you specify in % the ContentTypeField. In this description * means any subtype. % % application/json % Data is converted to a Unicode string using the jsonencode function, % and that string is converted to uint8 based on the charset (default % UTF-8) using unicode2native. If you already have a JSON-encoded string % that you want to send in a message with a Content-Type of % application/json, set the Payload property to the string or character % vector. That string will then be converted to uint8 using the charset % in the ContentTypeField, or by default, UTF-8. % % text/* (any subtype other than csv or xml) % If Data is a character or string array or cell array of character % vectors, it will be reshaped and concatenated by row to form a vector. % If data is of any other type, it will be converted to a string using % the string function. The resulting string will be converted to uint8 % based on the charset. If you did not specify a charset, the default % depends on the subtype. For these subtypes: % json jtml javascript css calendar % the default is UTF-8. For all other subtypes, MATLAB examines the % string to determine the charset. If all characters are in the ASCII % range, the charset is US-ASCII. Otherwise the charset is UTF-8. Note % that text types encoded as UTF-8, without an explicit charset % that says UTF-8, may not be interpreted properly by servers, so it is % best to specify UTF-8 explicitly if you think that your data is % non-ASCII. % % image/* % Data must be MATLAB image data in any form acceptable as the first % argument to to imwrite (e.g., M-by-N, M-by-N-by-3). Conversion of that % data to uint8 depends on the subtype. The following subtypes are % supported: % % subtype format used by imwrite % ------- -------------------------- % bmp bmp % gif gif % jpeg jpeg % jp2 jp2 % jpx jpx % png png % tiff tiff % x-hdf hdf % x-portable-bitmap pbm % x-pcx pcx % x-portable-graymap pgm % x-portable-anymap pnm % x-portable-pixmap ppm % x-cmu-raster ras % x-xwd xwd % % If the subtype is any value not in the above list, the subtype will be % passed into imwrite as the format, which may or may not succeed. % % You can more finely control conversion of your image data to a payload, % or override the type of conversion based on the subtype above, by % specifying parameters to imwrite, other than the filename, in a cell % array. In this case, if you specify a fmt argument (the image format), % it will override any conversion assumed above. For example: % % body = MessageBody({imageData, 'jpg', 'Quality', 50}); % req = RequestMessage('put', ContentTypeField('image/jpeg'), body); % resp = req.send(url); % % would convert imageData to JPEG with compression quality 50, and % send it with 'image/jpeg' Content-Type to the specified url. % % application/xml % text/xml % If data is an XML DOM in the form of a Java org.w3c.dom.Document object % (such as that returned the xmlread function), it will be converted to a % string using xmlwrite. If it is already a string or character vector, % it will be unchanged. The string will be converted to uint8 using the % specified charset (default UTF-8). % % audio/* % Data must be a cell array of at least two values, an m-by-n matrix of % audio data and a sampling rate in Hz, as described for audiowrite. You % can specify additional parameters to audiowrite by adding additional % arguments to the cell array. The following types are recognized: % % audio/x-wav audio/wav audio/mp4 % audio/vnd.wav application/ogg audio/flac % % application/csv % text/csv % application/vnd.openxmlformats-officedocument.spreadsheetml.sheet % application/vnd.ms-excel % If data is a table, it is converted using writetable. For the csv % subtypes, it and will be converted to comma-delimited text using the % specified charset (default ASCII). For the other types it will be % converted to Excel spreadsheet data. If you want to specify additional % arguments (Name,Value pairs) to writetable, include the data in a cell % array containing the additional arguments. If these additional % arguments include a 'FileType', that type must be consistent with the % subtype you specify. If data is a string or character vector, it will % be sent unconverted as string using the charset specified in the % content type (default US-ASCII for text/csv and UTF-8 for the others). % % If you do not specify a ContentTypeField in the RequestMessage, MATLAB % attempts to guess the type, subtype and charset by examining the Data, and % then processes the Data as above. This guess may not result in the % Content-Type you intended, or may fail to determine the type, so it is % generally best to specify the Content-Type. The following describes the % assumed Content-Type based on the data. Other types not listed below may % be handled as well, but behavior for unlisted types is not guaranteed to % remain the same in future releases. % % string, character array, cell array of character vectors % text/plain % % table % text/csv % % cell vector whose first element is table % If there is a name,value pair in the vector with the value % 'FileType','csv' or there is no such pair, Content-Type is text/csv. % If the FileType says 'spreadsheet' then the Content-Type is % application/vnd.openxmlformats-officedocument.spreadsheetml.sheet. % % org.w3c.dom.Document % application/xml % % If you have a uint8 vector of bytes to send and do not want any conversion % on the data regardless of what is in the ContentTypeField, set Payload % instead of Data. If you want to send character-based data with no % conversion other than the charset, and you are not specifying a % ContentTypeField with one of the above content types that would process % character data (such as application/json), you can set Data to a string or % character vector. For types that would process character data, set % Payload to that string or character vector. % % Input Conversion for ResponseMessage % ------------------------------------ % % The following is a list of the Content-Types that MATLAB recognizes in a % ResponseMessage based the type/subtype and charset in the received % ContentTypeField. These conversions are done only if % HTTPOptions.ConvertResponse is true (which is the default). A * below % means any characters. % % application/json % Data is converted to a string based on the charset (default UTF-8) and % then to MATLAB data using jsondecode. % % image/* % Data is converted to an image using imread with the specified subtype as % the format, using default arguments. If imread returns more than one % value (e.g., an indexed image such as a GIF also returns a colormap, and % a PNG image also returns an alpha channel), then Data is a cell array of % those values. The types of image data supported is the same as that % listed above for image/* in a RequestMessage. % % audio/* % Data is converted using audioread to a cell array of two values, an % m-by-n matrix of audio data and a sampling rate in Hz. The subtype % determines the format used by audioread. The types recognized are: % % audio/wav audio/x-wav audio/vnd.wav audio/mp4 audio/flac % % Note that application/ogg is missing from this list because ogg data % does not necessarily contain audio only. % % text/csv % text/comma-separated-values % application/csv % application/comma-separated-values % Data is converted to table using readtable, with assumed FileType of % csv and charset, if specified, or MATLAB's default encoding. % % application/*spreadsheet* % Data is converted to table using readtable, with assumed FileType % spreadsheet. % % text/xml % application/xml % If Java is available, data is converted to a Java org.w3c.dom.Document % using xmlread. If Java is not available, data is processed as % text/plain with the UTF-8 charset. % % If the type is not one of those listed above, then MATLAB determines % whether it is one of the character-based types: % text/* % any type mentioning a charset % application/*javascript % application/x-www-form-urlencoded % application/vnd.wolfram.mathematica.package % MATLAB converts these types to a string, using the charset, if specified, % or US-ASCII for text/plain, UTF-8 for the application types, and MATLAB's % default encoding for the other types. % % Incoming Content-Types other than those above may be converted in the % future. If the type is not one of those that MATLAB recognizes, or if % HTTPOptions.ConvertResponse is false, Data will contain the payload % converted to string if the type is character-based as listed above, or the % raw uint8 vector otherwise. % % If conversion of incoming data is attempted but fails (for example, % image/jpeg data is not valid JPEG data) the History property in the % HTTPException thrown by RequestMessage.send will contain the % ResponseMessage with Payload set to the uint8 payload and, if the type is % character-based as listed above, the Data set to the payload converted to % a string. % % See also Payload, RequestMessage, ResponseMessage, imwrite, imread, % audiowrite, audioread, matlab.net.http.field.ContentTypeField, % matlab.net.http.HTTPException.History, % matlab.net.http.HTTPOptions.ConvertResponse, jsonencode, jsondecode, % xmlwrite, xmlread Data % scalar string, vector of char, struct or uint8, anything else % Payload - the raw bytes as a uint8 vector % In a RequestMessage, you can set this property to a uint8 vector, instead % of Data, if you do not want any output conversion or charset encoding on % the array of bytes. If you set Data instead the data will be converted % based on the ContentTypeField as described for the Data property, and the % COMPLETEDREQUEST returned by RequestMesage.send or RequestMessage.complete % will contain that converted data in the Payload property. In a % ReponseMessage, this property will contain the uint8 vector received from % the server, prior to conversion, if you specified HTTPOptions.SavePayload. % % As a convenience, if you store a scalar string or character vector in this % property, it will be converted to a uint8 vector using the charset % specified in or implied by the ContentType property in the MessageBody, if % any, or UTF-8 if none was set. If you desire a different encoding, you % must encode it yourself (using unicode2native, for example) and store the % resulting uint8 vector here. Note that ContentType is not set in a new % MessageBody until the MessageBody is stored in a RequestMessage that % contains a ContentTypeField. % % No data types other than uint8 vectors, scalar strings, or character % vectors are permitted here. The result is always a uint8 vector. % % When you set this property, Data is cleared. If you send a message where % both Data and Payload are already set, Payload is sent and Data is % ignored. Only ResponseMessages and RequestMessages returned by % RequestMessage.send or RequestMessage.complete can have both properties % set at the same time. % % In a ResponseMessage returned by RequestMessage.send, this property is set % to the raw bytes received if you specify a history return argument or % HTTPOptions.SavePayload. It is also set in the ResponseMessage in the % History of an HTTPException if conversion of the payload to MATLAB data % failed. % % See also Data, RequestMessage, ResponseMessage, LogRecord, % matlab.net.http.HTTPOptions.SavePayload, unicode2native, HTTPException Payload end properties (Access={?matlab.net.http.internal.HTTPConnector, ... ?matlab.net.http.RequestMessage, ... ?matlab.net.http.ResponseMessage}, Hidden) % The real Payload, uint8 vector. Unlike Payload, Setting this does not % change PayloadLength or clear Data. PayloadInt % The real Data DataInt end properties (GetAccess={?matlab.net.http.ResponseMessage}, ... SetAccess={?matlab.net.http.RequestMessage, ... ?matlab.net.http.ResponseMessage, ... ?matlab.net.http.internal.HTTPConnector}, Hidden) % The PayloadLength, set each time Payload is set, but not changed when % PayloadInt is set. Internal classes can set this to the payload length % without actually setting a payload, to indicate the size of the original % payload when HTTPOptions.SavePayload was false. PayloadLength % uint64 or [] end properties (SetAccess={?matlab.net.http.Message,?matlab.net.http.RequestMessage}, Transient) % ContentType - Content-Type of the data (a MediaType, read-only) % This value is a MediaType with contents identical to what would be % obtained from calling ContentTypeField.convert() on the Content-Type field % in the message containing this MessageBody. This property determines how % contents of the Data property will be or was converted. If the % Content-Type has a MediaType with a charset parameter, or implies a % particular charset, that charset determines the encoding. % % You cannot set this property directly. When you create a MessageBody, % this property is initially empty. It is also set to empty any time you % set Data. When you copy a MessageBody into a RequestMessage, or if you % add a Content-Type field to the header, this property will be set to the % value of the ContentTypeField, if there is one. Otherwise it is left % empty. The send and complete methods of RequestMessage then set this % property based on the type of data you store in Data and the value of the % ContentTypeField in the RequestMessage, as described for the Data % property. % % In an incoming message, this is normally the Content-Type in the % ResponseMessage. If Data is present this property indicates what % conversion was done on the payload. If Data is not present (due to a % conversion error or suppressed conversion by setting % HTTPOptions.ConvertResponse to false) this indicates the conversion that % should be done or was attempted on the payload. % % If conversion of the payload required two steps: first charset and then % type/subtype (as is done for application/json or application/xml), but % only the charset conversion was done (due to an unknown type or subtype, a % conversion error, or suppressed conversion because % HTTPOptions.ConvertResponse was false), Data contains the Unicode string % and this property contains only the charset (i.e., Type and Subtype are % empty). % % If you set Data, this property is cleared. If you set Payload, this % property is unchanged. % % See also Data, Payload, MediaType, RequestMessage, ResponseMessage, % matlab.net.http.field.ContentTypeField ContentType % MediaType or [] % ContentCoding - Content-Encoding of the payload (read-only) % This property is set to indicate that the Payload of a received message % is encoded. When this is set, no processing was done on the payload and % Data is empty. % % If MATLAB receives a message whose payload is encoded using a compression % algorithm that it supports, such as gzip or deflate, it automatically % decodes that payload before attempting any other conversions. If decoding % was successful, it optionally stores the decoded payload in Payload and % the converted payload (if any) in Data. In that case, this property is % empty to indicate that the Payload is not encoded. % % If the payload was encoded but decoding was not successful, or you % suppressed decoding by setting HTTPOptions.DecodePayload to false, the % unprocessed still-encoded payload is returned in Payload, Data is left % empty, and this property is set to a vector of strings representing the % value of the Content-Encoding header field in the ResponseMessage. In % this case you can save the Payload as is (e.g., write it to a file), or % process it according to the compression algorithm(s) specified in this % property. For example if the value is 'gzip' you can write the data to a % file and use the gunzip command to process the data. ContentCoding string = string.empty end methods function obj = MessageBody(data) if nargin > 0 obj.DataInt = data; end end function obj = set.Data(obj, data) obj.DataInt = data; obj.PayloadInt = []; obj.PayloadLength = []; obj.ContentType = []; end function data = get.Data(obj) data = obj.DataInt; end function obj = set.Payload(obj, value) % Normally this is set to a uint8 by the infrastructure, but we also allow % the user to set this to a string, in which case we'll convert it to native % using the charset in the ContentType, if any, or utf-8. if isempty(value) obj.PayloadInt = []; obj.PayloadLength = []; else if (ischar(value) && isvector(value)) || (isstring(value) && isscalar(value)) charset = 'utf-8'; if ~isempty(obj.ContentType) cs = matlab.net.internal.getCharsetForMediaType(obj.ContentType); if ~isempty(cs) charset = cs; end end value = unicode2native(char(value), char(charset)); % TBD string else validateattributes(value, {'uint8'}, {'vector'}, mfilename, 'Payload'); end obj.PayloadInt = value; obj.PayloadLength = length(value); end obj.DataInt = []; end function value = get.Payload(obj) value = obj.PayloadInt; end function str = string(obj) % string Return the Data converted to a string % STR = string(BODY) % This method is intended for display or logging only. It returns the Data % only if it is a scalar string or character vector. If it is anything % else, it returns a short message indicating the length of Payload in bytes % (if set) or the length that the Payload would be if the MessageBody is % sent in a RequestMessage. % % See also show, Payload, RequestMessage data = obj.DataInt; if (ischar(data) && isvector(data)) || (isstring(data) && isscalar(data)) % Data is a char vector or string str = string(data); else % it's not a string or data not set str = obj.getNonCharString(); end end function str = char(obj) % string Return the Data converted to a character vector % For a description see string. % % See also string, show str = char(obj.string()); end function str = show(obj, maxLength) % show Display or returns a human-readable version of the data % show(BODY) displays the entire body if it is character data % show(BODY,MAXLENGTH) displays at most MAXLENGTH characters of the data. % If the data is longer than MAXLENGTH, it also displays a line indicating % the total length in characters. % STR = show(___) returns the output as a string instead of displaying it. % % This method is intended for diagnostics or debugging. It displays or % returns the Data only if is a scalar string or char vector. If it is % anything else, it returns a short message indicating the length of % Payload in bytes (if known) or, if Payload length is not known, the % length that the Payload would be if this BODY were to be sent in a % RequestMessage. % % See also string, char, Payload, RequestMessage data = obj.DataInt; if ~ischar(data) && ~isstring(data) % It's not a string or data not set; convert data to string. This % could be extremely long, so it's subject to truncation. [data, lengthMsg] = obj.getNonCharString(); if lengthMsg % Not character data; it's just a message about length; so always print it lenMsg = data; len = 0; else % It's the converted data len = strlength(data); if nargin > 1 && len > maxLength lenMsg = obj.bodyLengthMessageChars(len); end end else [data, len] = matlab.net.internal.getSingleStringFromData(data); if nargin > 1 && len > maxLength lenMsg = obj.bodyLengthMessageChars(len); end end if nargin > 1 && len > maxLength % Too long, output just the beginning and total length if isstring(data) chars = data.extractBetween(1,maxLength); else chars = data(1:maxLength); end if nargout == 0 fprintf('%s\n\n%s\n', chars, lenMsg); else str = sprintf('%s\n\n%s\n', chars, lenMsg); end else if nargout == 0 fprintf('%s\n',data); else str = string(data); end end end end methods (Access=private) function [len, bytes] = getLengthBytes(obj) % getLength get length and contents of payload % [len, bytes] = getLengthBytes(BODY) returns length of payload in bytes % and optionally bytes of the payload. % If only len requested: % If PayloadLength is set, return it % If PayloadLength and Payload not set, but Data is set, convert Data % to Payload and return its length in bytes % If both len and bytes are requested: % If Payload is set, return its length and bytes. % If Payload not set but Data is set, convert Data to Payload and % return its length and bytes. This may return a length different % from that in PayloadLength. % % To determine the actual number of bytes in a received message prior to % conversion, set HTTPOptions.SavePayload or request history when sending % the message. if nargout > 1 || isempty(obj.PayloadLength) bytes = obj.getBytes(); % simply returns Payload if set, or converts len = length(bytes); else len = obj.PayloadLength; end end function bytes = getBytes(obj) % getBytes returns the payload as a uint8 array of types % If this is invoked on a MessageBody whose Payload has been set, this % simply returns the Payload. Otherwise this returns the bytes that would % be sent if this MessageBody is used in an outgoing message and there is % no Content-Type specified in the RequestMessage. If you created this % MessageBody for an outgoing message and haven't yet called send or % complete in the RequestMessage, the ContentType will not yet be set and % these bytes will be converted based only on the type of Data, as % described for the Data property. If you set the ContentTypeField of the % RequestMessage and then call complete, the returned RequestMessage will % contain a Body whose ContentType is set to that of the ContentTypeField, % resulting in possibly different conversion. % % In an incoming message where Data has already been converted from the % payload based on the incoming ContentType, but Payload has not been set % in this object (for example, because you didn't specify 'SavePayload' in % HTTPOptions), calling this method will give you the bytes that would be % sent if you used this MessageBody, along with its ContentType, in a % RequestMessage. This may not necessarily be the same bytes that were % received, since conversion is not exactly reversible. % % See also Payload, RequestMessage, ResponseMessage, HTTPOptions.SavePayload if ~isempty(obj.PayloadInt) % If we have a payload, that's the bytes bytes = obj.PayloadInt; return; end data = obj.DataInt; if isempty(data) bytes = []; return; end bytes = matlab.net.http.internal.data2payload(data, obj.ContentType); end function str = bodyLengthMessageBytes(obj) % Return message indicating total length of payload or data in bytes if ~isempty(obj.ContentType) if isempty(obj.ContentCoding) mediaType = obj.ContentType.Type + '/' + obj.ContentType.Subtype; else mediaType = strjoin(obj.ContentCoding, ', '); end msg = message('MATLAB:http:BytesOfContentData', obj.getLengthBytes(), char(mediaType)); else msg = message('MATLAB:http:BytesOfData', obj.getLengthBytes()); end str = string(msg.getString()); end function str = bodyLengthMessageChars(obj, len) % Return message indicating total length of data in characters; obj.DataInt % must be a char vector or string if nargin < 2 if ischar(obj.DataInt) len = length(obj.DataInt); else len = strlength(obj.DataInt); end end if ~isempty(obj.ContentType) mediaType = obj.ContentType.Type + '/' + obj.ContentType.Subtype; mediaType = mediaType + ' ' + upper(matlab.net.internal.getCharsetForMediaType(obj.ContentType)); msg = message('MATLAB:http:TotalCharsOfContentData', len, char(mediaType)); else msg = message('MATLAB:http:TotalCharsOfData', len); end str = string(msg.getString()); end function [str, lengthMsg] = getNonCharString(obj) % Stringify non-string data, if possible. Otherwise return a message about % the data's length in bytes. Called when type of Data is not string or char % (it's [] or some other type). If [] and there is a ContentType that has a % charset, convert Payload to string based on charset; otherwise return length % message. lengthMsg == true says str is a message about the length of the % data; if false str is the actual data as a string. if ~isempty(obj.Data) && ~isempty(obj.ContentType) charset = matlab.net.internal.getCharsetForMediaType(obj.ContentType); if ~isempty(charset) % If there is an explicit or default charset, get the bytes, % either by converting the Data or directly from Payload, and % return them as a Unicode string bytes = obj.getBytes(); str = string(native2unicode(bytes(:)', char(charset))); % TBD string lengthMsg = false; return; else end end % Data not characters; just return length message in bytes str = obj.bodyLengthMessageBytes(); lengthMsg = true; end end end