www.gusucode.com > external 工具箱matlab源码程序 > external/interfaces/webservices/http/+matlab/+net/+http/+internal/readContentFromWebService.m

    function [data, payloadLength, payload, charset] = readContentFromWebService(arg1, arg2, convert, raw)
%readContentFromWebService Read content from Web service
%   [data, payloadLength, payload] = readContentFromWebService(connector, log, convert, raw)
%   reads the content from the Web service indicated by connector and returns the
%   response in data and payload, and the original payloadLength.  If convert is
%   set, the response is decoded based on connector.ContentType and returned in data.
%   If there is no ContentType, process as application/octet-stream (as per section
%   3.1.1.5 of RFC 7231), which returns a uint8 vector.  Caller can do "content
%   sniffing" if this is needed.
%
%   data = readContentFromWebService(payload, contentType) is the same, but reads and
%   converts the payload already in memory using the specified contentType or
%   application/octet-stream as above.  This form is used to re-convert a
%   payload received from the web that was improperly converted or which was
%   not converted the first time.
%
%   connector - a HTTPConnector object on which a request has been sent and
%               response received.  Returns empty if the connector has no response
%               message or the response has no content.  We use connector.ContentType
%               to determine the contentType for conversion.
%
%   log       - call connector.log to log the message containing this data
%
%   convert   - Used only if raw is false: If true, convert the payload to MATLAB 
%               data based on contentType and return in data.  If false, just
%               convert payload to Unicode based on charset in or implied by the
%               contentType.  If false and there is no charset, return raw
%               uint8 vector in data (same as payload).
%
%   raw       - (optional) If true, just return raw payload and leave data [].  In
%               this case payload must be specified.
%
%   contentType - the MediaType to use to convert the data or []
%
%   data      - the data, converted based on connector.Content-Type and charset and
%               whether convert is specified.
%
%   payloadLength - the length of the unconverted payload; useful when payload is not
%               being returned.
%
%   payload   - the unconverted data as a uint8 array.
%
%   charset   - If convert = false or raw = true, and contentType is character
%               data that we are returning in data, this is the charset we
%               used to convert the payload.  The purpose of this is to
%               communicate the charset when we didn't do a full conversion of
%               payload based on contentType, but only converted the
%               characters to Unicode.

% Copyright 2015-2016 The MathWorks, Inc.

    % Convert the ContentType in the received message (e.g. text/plain,
    % application/json, etc) to a simple form (e.g. text, image, json, etc.)
    useConnector = isa(arg1, 'matlab.net.http.internal.HTTPConnector');
    if useConnector
        connector = arg1;
        log = arg2;
        contentType = lower(connector.ContentType);
        if isempty(contentType)
            mediaType = [];
        else
            mediaType = matlab.net.http.MediaType(contentType);
        end
    else
        payload = arg1;
        mediaType = arg2;
        log = false;
    end
    if nargin < 4
        raw = false;
    end
    if ~raw
        if isempty(mediaType)
            simpleType = [];
            charset = '';
        else
            simpleType = matlab.net.http.internal.getSimpleType(mediaType);
            subtype = lower(mediaType.Subtype);
            % this may return '' if no charset can be determined
            charset = matlab.net.internal.getCharsetForMediaType(mediaType);
        end
    else
        % expect payload if raw specified
        assert(nargout > 1)
    end    
    if ~raw && (~useConnector || convert) && ~isempty(simpleType)
        downloadToFile = contentRequiresFileDownload(simpleType);
        if downloadToFile
            filename = getTempname(simpleType, subtype);
            if isempty(filename)
                % empty filename means we can't convert it, so just return raw data
                downloadToFile = false;
                convert = false;
            end
        end
    else
        downloadToFile = false;
    end
    
    if downloadToFile
        % We take this path only when convert = true and we need to write it to a
        % file in order to convert it.
        cleanup = onCleanup(@()deleteFile(filename));
        if useConnector
            % This downloads the data from the server into the file
            connector.copyContentToFile(filename);
        else
            % payload was set above in the ~useConnector case
            f = fopen(filename, 'w');
            cleanf = onCleanup(@()fclose(f));
            fwrite(f, payload);
            payloadLength = length(payload);
            clear cleanf
        end
        e = [];
        try
            % Read it back, possibly using charset for simpleType = 'text', using the
            % converter based on simpleType and charset.  This function assumes we
            % don't call it for simpleTypes like 'json' that don't require file
            % download.
            data = matlab.net.http.internal.readContentFromFile(filename, ...
                                                     charset, simpleType, subtype);
            if exist('payload','var')
                payloadLength = length(payload);
            else
                % If we were called with a 1st argument of HTTPConnector, the payload was
                % written directly to the file, not passed in, so get its length.
                info = dir(filename);
                payloadLength = info.bytes;
            end
        catch e
            % just save the exception; it's some non-HTTP exception
        end
        if (~isempty(e) || nargout > 1 || log) && exist(filename,'file')
            % if there was an exception, or we need to get the payload for logging,
            % and the file was created, then fetch the payload from the file.
            f = fopen(filename,'r','n');
            clean2 = onCleanup(@()fclose(f));
            payload = fread(f,Inf','uint8=>uint8');
            payloadLength = length(payload);
            clear clean2
        end
        if ~isempty(e) 
            % If an exception occurred reading or converting content, throw
            % MATLAB:http exception with a special message that includes the message
            % in the exception.
            if useConnector
                me = MException(message('MATLAB:http:CannotConvertContent', ...
                                        char(connector.URI), char(mediaType)));
            else
                me = MException(message('MATLAB:http:CannotConvertPayload', ...
                                        char(mediaType)));
            end
            % Add e as the cause just so we can get its stack trace.
            % Adding e as the cause here will cause the message to be duplicated when
            % getReport is called on me, but this is the only way to get the original
            % stack to appear, since we can't directly set me.stack.
            me = me.addCause(e);
            % Throw an HTTPException that contains a history and a ResponseMessage with
            % the payload filled in.
            if isempty(charset)
                throw(matlab.net.http.internal.ExceptionWithPayload(payload, me));
            else
                % If there is a charset, then also populate data with the characters.  This gives
                % us human-readable input in ResponseMessage.Body.Data.
                data = string(native2unicode(payload', char(charset)));
                throw(matlab.net.http.internal.ExceptionWithPayload(payload, me, data, charset));
            end
        end
        % conversion successful, no charset in this case
        charset = [];
    else
        % convert is false or content can be decoded without file download.
        % Copy the raw data stream from the connection to byteArray.
        if useConnector
            payload = connector.copyContentToByteArray();
            url = char(connector.URI);
        else
            url = [];
        end
        payloadLength = length(payload);
        if raw
            data = [];
            charset = [];
        else
            % Decode the byte array. Here, simpleType and charset may be empty.
            % This throws ExceptionWithPayload if decoding or conversion failed.
            data = matlab.net.http.internal.decodeByteArray(payload, charset, ...
                                                           simpleType, url, convert);
            if convert || isempty(simpleType)
                % if data was converted or there was no simpleType (indicating we're just
                % returning the binary data), don't return a charset.
                charset = [];
            end
        end
    end
    
    if log
        connector.log(data, payload);
    end
end


%--------------------------------------------------------------------------

function fname = getTempname(simpleType, subtype)
% Return a temp file name for downloading content.  subtype must be string
    fname = tempname;
    suffix = matlab.net.http.internal.getSuffixForSubtype(simpleType, subtype);
    if isempty(suffix)
        if ~ischar(suffix)
            % suffix of [] indicates we recognize the simpleType but don't know how to
            % convert the subtype
            fname = [];
        end
    else
        fname = [fname '.' suffix];        
    end
end

%--------------------------------------------------------------------------

function downloadToFile = contentRequiresFileDownload(simpleType)
    % Return true if content requires downloading to a file.

    downloadToFile = any(strcmpi(simpleType,{'image','table','xmldom','audio'}));
end

%--------------------------------------------------------------------------

function deleteFile(filename)
    % Delete filename, if it exists.

    if exist(filename, 'file')
        delete(filename)
    end
end