zoukankan      html  css  js  c++  java
  • Rclone webapi 使用例子

    Rclone 支持命令模式调用,同时也支持webapi形式调用。使用webapi调用模式,例子如下

    1、启动Rclone,以下为powershell 代码

    #包含webgui的启动,浏览器访问127.0.0.1:5572 有web界面
    .
    clone
    clone.exe rcd --rc-web-gui --rc-addr="127.0.0.1:5572" --rc-user=abc --rc-pass=abc  --rc-files="E:
    clonewebgui" --rc-allow-origin="127.0.0.1:5572"  
    #或不包含webgui的启动,无web访问
    .
    clone
    clone.exe rcd  --rc-addr="127.0.0.1:5572" --rc-user=abc --rc-pass=abc  --rc-allow-origin="127.0.0.1:5572" 

    2、使用指令类似如下

    .
    clone rc --user abc --pass abc rc/list

    3、支持的command如下

    {
        "commands":[
            {
                "AuthRequired":true,
                "Help":"This takes the following parameters
    
    - command - a string with the command name
    - fs - a remote name string eg "drive:"
    - arg - a list of arguments for the backend command
    - opt - a map of string to string of options
    
    Returns
    
    - result - result from the backend command
    
    For example
    
        rclone rc backend/command command=noop fs=. -o echo=yes -o blue -a path1 -a path2
    
    Returns
    
    ```
    {
    "result": {
    "arg": [
    "path1",
    "path2"
    ],
    "name": "noop",
    "opt": {
    "blue": "",
    "echo": "yes"
    }
    }
    }
    ```
    
    Note that this is the direct equivalent of using this "backend"
    command:
    
        rclone backend noop . -o echo=yes -o blue path1 path2
    
    Note that arguments must be preceded by the "-a" flag
    
    See the [backend](/commands/rclone_backend/) command for more information.",
                "Path":"backend/command",
                "Title":"Runs a backend command."
            },
            {
                "AuthRequired":true,
                "Help":"This takes the following parameters
    
    - name - name of remote
    - parameters - a map of { "key": "value" } pairs
    - type - type of the new remote
    - obscure - optional bool - forces obscuring of passwords
    - noObscure - optional bool - forces passwords not to be obscured
    
    
    See the [config create command](/commands/rclone_config_create/) command for more information on the above.",
                "Path":"config/create",
                "Title":"create the config for a remote."
            },
            {
                "AuthRequired":true,
                "Help":"Parameters:
    
    - name - name of remote to delete
    
    See the [config delete command](/commands/rclone_config_delete/) command for more information on the above.",
                "Path":"config/delete",
                "Title":"Delete a remote in the config file."
            },
            {
                "AuthRequired":true,
                "Help":"Returns a JSON object:
    - key: value
    
    Where keys are remote names and values are the config parameters.
    
    See the [config dump command](/commands/rclone_config_dump/) command for more information on the above.",
                "Path":"config/dump",
                "Title":"Dumps the config file."
            },
            {
                "AuthRequired":true,
                "Help":"Parameters:
    
    - name - name of remote to get
    
    See the [config dump command](/commands/rclone_config_dump/) command for more information on the above.",
                "Path":"config/get",
                "Title":"Get a remote in the config file."
            },
            {
                "AuthRequired":true,
                "Help":"Returns
    - remotes - array of remote names
    
    See the [listremotes command](/commands/rclone_listremotes/) command for more information on the above.",
                "Path":"config/listremotes",
                "Title":"Lists the remotes in the config file."
            },
            {
                "AuthRequired":true,
                "Help":"This takes the following parameters
    
    - name - name of remote
    - parameters - a map of { "key": "value" } pairs
    
    
    See the [config password command](/commands/rclone_config_password/) command for more information on the above.",
                "Path":"config/password",
                "Title":"password the config for a remote."
            },
            {
                "AuthRequired":true,
                "Help":"Returns a JSON object:
    - providers - array of objects
    
    See the [config providers command](/commands/rclone_config_providers/) command for more information on the above.",
                "Path":"config/providers",
                "Title":"Shows how providers are configured in the config file."
            },
            {
                "AuthRequired":true,
                "Help":"This takes the following parameters
    
    - name - name of remote
    - parameters - a map of { "key": "value" } pairs
    - obscure - optional bool - forces obscuring of passwords
    - noObscure - optional bool - forces passwords not to be obscured
    
    
    See the [config update command](/commands/rclone_config_update/) command for more information on the above.",
                "Path":"config/update",
                "Title":"update the config for a remote."
            },
            {
                "AuthRequired":false,
                "Help":"This sets the bandwidth limit to that passed in.
    
    Eg
    
        rclone rc core/bwlimit rate=off
        {
            "bytesPerSecond": -1,
            "rate": "off"
        }
        rclone rc core/bwlimit rate=1M
        {
            "bytesPerSecond": 1048576,
            "rate": "1M"
        }
    
    
    If the rate parameter is not supplied then the bandwidth is queried
    
        rclone rc core/bwlimit
        {
            "bytesPerSecond": 1048576,
            "rate": "1M"
        }
    
    The format of the parameter is exactly the same as passed to --bwlimit
    except only one bandwidth may be specified.
    
    In either case "rate" is returned as a human readable string, and
    "bytesPerSecond" is returned as a number.",
                "Path":"core/bwlimit",
                "Title":"Set the bandwidth limit."
            },
            {
                "AuthRequired":false,
                "Help":"This tells the go runtime to do a garbage collection run.  It isn't
    necessary to call this normally, but it can be useful for debugging
    memory problems.",
                "Path":"core/gc",
                "Title":"Runs a garbage collection."
            },
            {
                "AuthRequired":false,
                "Help":"This returns list of stats groups currently in memory. 
    
    Returns the following values:
    ```
    {
    "groups":  an array of group names:
    [
    "group1",
    "group2",
    ...
    ]
    }
    ```",
                "Path":"core/group-list",
                "Title":"Returns list of stats."
            },
            {
                "AuthRequired":false,
                "Help":"This returns the memory statistics of the running program.  What the values mean
    are explained in the go docs: https://golang.org/pkg/runtime/#MemStats
    
    The most interesting values for most people are:
    
    * HeapAlloc: This is the amount of memory rclone is actually using
    * HeapSys: This is the amount of memory rclone has obtained from the OS
    * Sys: this is the total amount of memory requested from the OS
      * It is virtual memory so may include unused memory",
                "Path":"core/memstats",
                "Title":"Returns the memory statistics"
            },
            {
                "AuthRequired":false,
                "Help":"Pass a clear string and rclone will obscure it for the config file:
    - clear - string
    
    Returns
    - obscured - string",
                "Path":"core/obscure",
                "Title":"Obscures a string passed in."
            },
            {
                "AuthRequired":false,
                "Help":"This returns PID of current process.
    Useful for stopping rclone process.",
                "Path":"core/pid",
                "Title":"Return PID of current process"
            },
            {
                "AuthRequired":false,
                "Help":"(optional) Pass an exit code to be used for terminating the app:
    - exitCode - int",
                "Path":"core/quit",
                "Title":"Terminates the app."
            },
            {
                "AuthRequired":false,
                "Help":"This returns all available stats:
    
    rclone rc core/stats
    
    If group is not provided then summed up stats for all groups will be
    returned.
    
    Parameters
    
    - group - name of the stats group (string)
    
    Returns the following values:
    
    ```
    {
    "speed": average speed in bytes/sec since start of the process,
    "bytes": total transferred bytes since the start of the process,
    "errors": number of errors,
    "fatalError": whether there has been at least one FatalError,
    "retryError": whether there has been at least one non-NoRetryError,
    "checks": number of checked files,
    "transfers": number of transferred files,
    "deletes" : number of deleted files,
    "renames" : number of renamed files,
    "elapsedTime": time in seconds since the start of the process,
    "lastError": last occurred error,
    "transferring": an array of currently active file transfers:
    [
    {
    "bytes": total transferred bytes for this file,
    "eta": estimated time in seconds until file transfer completion
    "name": name of the file,
    "percentage": progress of the file transfer in percent,
    "speed": speed in bytes/sec,
    "speedAvg": speed in bytes/sec as an exponentially weighted moving average,
    "size": size of the file in bytes
    }
    ],
    "checking": an array of names of currently active file checks
    []
    }
    ```
    Values for "transferring", "checking" and "lastError" are only assigned if data is available.
    The value for "eta" is null if an eta cannot be determined.",
                "Path":"core/stats",
                "Title":"Returns stats about current transfers."
            },
            {
                "AuthRequired":false,
                "Help":"This deletes entire stats group
    
    Parameters
    
    - group - name of the stats group (string)",
                "Path":"core/stats-delete",
                "Title":"Delete stats group."
            },
            {
                "AuthRequired":false,
                "Help":"This clears counters, errors and finished transfers for all stats or specific 
    stats group if group is provided.
    
    Parameters
    
    - group - name of the stats group (string)",
                "Path":"core/stats-reset",
                "Title":"Reset stats."
            },
            {
                "AuthRequired":false,
                "Help":"This returns stats about completed transfers:
    
    rclone rc core/transferred
    
    If group is not provided then completed transfers for all groups will be
    returned.
    
    Note only the last 100 completed transfers are returned.
    
    Parameters
    
    - group - name of the stats group (string)
    
    Returns the following values:
    ```
    {
    "transferred":  an array of completed transfers (including failed ones):
    [
    {
    "name": name of the file,
    "size": size of the file in bytes,
    "bytes": total transferred bytes for this file,
    "checked": if the transfer is only checked (skipped, deleted),
    "timestamp": integer representing millisecond unix epoch,
    "error": string description of the error (empty if successful),
    "jobid": id of the job that this transfer belongs to
    }
    ]
    }
    ```",
                "Path":"core/transferred",
                "Title":"Returns stats about completed transfers."
            },
            {
                "AuthRequired":false,
                "Help":"This shows the current version of go and the go runtime
    
    - version - rclone version, eg "v1.44"
    - decomposed - version number as [major, minor, patch, subpatch]
        - note patch and subpatch will be 999 for a git compiled version
    - isGit - boolean - true if this was compiled from the git version
    - os - OS in use as according to Go
    - arch - cpu architecture in use according to Go
    - goVersion - version of Go runtime in use",
                "Path":"core/version",
                "Title":"Shows the current version of rclone and the go runtime."
            },
            {
                "AuthRequired":false,
                "Help":"SetBlockProfileRate controls the fraction of goroutine blocking events
    that are reported in the blocking profile. The profiler aims to sample
    an average of one blocking event per rate nanoseconds spent blocked.
    
    To include every blocking event in the profile, pass rate = 1. To turn
    off profiling entirely, pass rate <= 0.
    
    After calling this you can use this to see the blocking profile:
    
        go tool pprof http://localhost:5572/debug/pprof/block
    
    Parameters
    
    - rate - int",
                "Path":"debug/set-block-profile-rate",
                "Title":"Set runtime.SetBlockProfileRate for blocking profiling."
            },
            {
                "AuthRequired":false,
                "Help":"SetMutexProfileFraction controls the fraction of mutex contention
    events that are reported in the mutex profile. On average 1/rate
    events are reported. The previous rate is returned.
    
    To turn off profiling entirely, pass rate 0. To just read the current
    rate, pass rate < 0. (For n>1 the details of sampling may change.)
    
    Once this is set you can look use this to profile the mutex contention:
    
        go tool pprof http://localhost:5572/debug/pprof/mutex
    
    Parameters
    
    - rate - int
    
    Results
    
    - previousRate - int",
                "Path":"debug/set-mutex-profile-fraction",
                "Title":"Set runtime.SetMutexProfileFraction for mutex profiling."
            },
            {
                "AuthRequired":false,
                "Help":"Parameters - None
    
    Results
    
    - jobids - array of integer job ids",
                "Path":"job/list",
                "Title":"Lists the IDs of the running jobs"
            },
            {
                "AuthRequired":false,
                "Help":"Parameters
    
    - jobid - id of the job (integer)
    
    Results
    
    - finished - boolean
    - duration - time in seconds that the job ran for
    - endTime - time the job finished (eg "2018-10-26T18:50:20.528746884+01:00")
    - error - error from the job or empty string for no error
    - finished - boolean whether the job has finished or not
    - id - as passed in above
    - startTime - time the job started (eg "2018-10-26T18:50:20.528336039+01:00")
    - success - boolean - true for success false otherwise
    - output - output of the job as would have been returned if called synchronously
    - progress - output of the progress related to the underlying job",
                "Path":"job/status",
                "Title":"Reads the status of the job ID"
            },
            {
                "AuthRequired":false,
                "Help":"Parameters
    
    - jobid - id of the job (integer)",
                "Path":"job/stop",
                "Title":"Stop the running job"
            },
            {
                "AuthRequired":true,
                "Help":"rclone allows Linux, FreeBSD, macOS and Windows to mount any of
    Rclone's cloud storage systems as a file system with FUSE.
    
    If no mountType is provided, the priority is given as follows: 1. mount 2.cmount 3.mount2
    
    This takes the following parameters
    
    - fs - a remote path to be mounted (required)
    - mountPoint: valid path on the local machine (required)
    - mountType: One of the values (mount, cmount, mount2) specifies the mount implementation to use
    
    Eg
    
        rclone rc mount/mount fs=mydrive: mountPoint=/home/<user>/mountPoint
        rclone rc mount/mount fs=mydrive: mountPoint=/home/<user>/mountPoint mountType=mount",
                "Path":"mount/mount",
                "Title":"Create a new mount point"
            },
            {
                "AuthRequired":true,
                "Help":"This shows all possible mount types and returns them as a list.
    
    This takes no parameters and returns
    
    - mountTypes: list of mount types
    
    The mount types are strings like "mount", "mount2", "cmount" and can
    be passed to mount/mount as the mountType parameter.
    
    Eg
    
        rclone rc mount/types",
                "Path":"mount/types",
                "Title":"Show all possible mount types"
            },
            {
                "AuthRequired":true,
                "Help":"rclone allows Linux, FreeBSD, macOS and Windows to
    mount any of Rclone's cloud storage systems as a file system with
    FUSE.
    
    This takes the following parameters
    
    - mountPoint: valid path on the local machine where the mount was created (required)
    
    Eg
    
        rclone rc mount/unmount mountPoint=/home/<user>/mountPoint",
                "Path":"mount/unmount",
                "Title":"Unmount all active mounts"
            },
            {
                "AuthRequired":true,
                "Help":"This takes the following parameters
    
    - fs - a remote name string eg "drive:"
    
    The result is as returned from rclone about --json
    
    See the [about command](/commands/rclone_size/) command for more information on the above.",
                "Path":"operations/about",
                "Title":"Return the space used on the remote"
            },
            {
                "AuthRequired":true,
                "Help":"This takes the following parameters
    
    - fs - a remote name string eg "drive:"
    
    See the [cleanup command](/commands/rclone_cleanup/) command for more information on the above.",
                "Path":"operations/cleanup",
                "Title":"Remove trashed files in the remote or path"
            },
            {
                "AuthRequired":true,
                "Help":"This takes the following parameters
    
    - srcFs - a remote name string eg "drive:" for the source
    - srcRemote - a path within that remote eg "file.txt" for the source
    - dstFs - a remote name string eg "drive2:" for the destination
    - dstRemote - a path within that remote eg "file2.txt" for the destination",
                "Path":"operations/copyfile",
                "Title":"Copy a file from source remote to destination remote"
            },
            {
                "AuthRequired":true,
                "Help":"This takes the following parameters
    
    - fs - a remote name string eg "drive:"
    - remote - a path within that remote eg "dir"
    - url - string, URL to read from
     - autoFilename - boolean, set to true to retrieve destination file name from url
    See the [copyurl command](/commands/rclone_copyurl/) command for more information on the above.",
                "Path":"operations/copyurl",
                "Title":"Copy the URL to the object"
            },
            {
                "AuthRequired":true,
                "Help":"This takes the following parameters
    
    - fs - a remote name string eg "drive:"
    
    See the [delete command](/commands/rclone_delete/) command for more information on the above.",
                "Path":"operations/delete",
                "Title":"Remove files in the path"
            },
            {
                "AuthRequired":true,
                "Help":"This takes the following parameters
    
    - fs - a remote name string eg "drive:"
    - remote - a path within that remote eg "dir"
    
    See the [deletefile command](/commands/rclone_deletefile/) command for more information on the above.",
                "Path":"operations/deletefile",
                "Title":"Remove the single file pointed to"
            },
            {
                "AuthRequired":false,
                "Help":"This takes the following parameters
    
    - fs - a remote name string eg "drive:"
    
    This returns info about the remote passed in;
    
    ```
    {
    // optional features and whether they are available or not
    "Features": {
    "About": true,
    "BucketBased": false,
    "CanHaveEmptyDirectories": true,
    "CaseInsensitive": false,
    "ChangeNotify": false,
    "CleanUp": false,
    "Copy": false,
    "DirCacheFlush": false,
    "DirMove": true,
    "DuplicateFiles": false,
    "GetTier": false,
    "ListR": false,
    "MergeDirs": false,
    "Move": true,
    "OpenWriterAt": true,
    "PublicLink": false,
    "Purge": true,
    "PutStream": true,
    "PutUnchecked": false,
    "ReadMimeType": false,
    "ServerSideAcrossConfigs": false,
    "SetTier": false,
    "SetWrapper": false,
    "UnWrap": false,
    "WrapFs": false,
    "WriteMimeType": false
    },
    // Names of hashes available
    "Hashes": [
    "MD5",
    "SHA-1",
    "DropboxHash",
    "QuickXorHash"
    ],
    "Name": "local",    // Name as created
    "Precision": 1,    // Precision of timestamps in ns
    "Root": "/",    // Path as created
    "String": "Local file system at /" // how the remote will appear in logs
    }
    ```
    
    This command does not have a command line equivalent so use this instead:
    
        rclone rc --loopback operations/fsinfo fs=remote:",
                "Path":"operations/fsinfo",
                "Title":"Return information about the remote"
            },
            {
                "AuthRequired":true,
                "Help":"This takes the following parameters
    
    - fs - a remote name string eg "drive:"
    - remote - a path within that remote eg "dir"
    - opt - a dictionary of options to control the listing (optional)
        - recurse - If set recurse directories
        - noModTime - If set return modification time
        - showEncrypted -  If set show decrypted names
        - showOrigIDs - If set show the IDs for each item if known
        - showHash - If set return a dictionary of hashes
    
    The result is
    
    - list
        - This is an array of objects as described in the lsjson command
    
    See the [lsjson command](/commands/rclone_lsjson/) for more information on the above and examples.",
                "Path":"operations/list",
                "Title":"List the given remote and path in JSON format"
            },
            {
                "AuthRequired":true,
                "Help":"This takes the following parameters
    
    - fs - a remote name string eg "drive:"
    - remote - a path within that remote eg "dir"
    
    See the [mkdir command](/commands/rclone_mkdir/) command for more information on the above.",
                "Path":"operations/mkdir",
                "Title":"Make a destination directory or container"
            },
            {
                "AuthRequired":true,
                "Help":"This takes the following parameters
    
    - srcFs - a remote name string eg "drive:" for the source
    - srcRemote - a path within that remote eg "file.txt" for the source
    - dstFs - a remote name string eg "drive2:" for the destination
    - dstRemote - a path within that remote eg "file2.txt" for the destination",
                "Path":"operations/movefile",
                "Title":"Move a file from source remote to destination remote"
            },
            {
                "AuthRequired":true,
                "Help":"This takes the following parameters
    
    - fs - a remote name string eg "drive:"
    - remote - a path within that remote eg "dir"
    
    Returns
    
    - url - URL of the resource
    
    See the [link command](/commands/rclone_link/) command for more information on the above.",
                "Path":"operations/publiclink",
                "Title":"Create or retrieve a public link to the given file or folder."
            },
            {
                "AuthRequired":true,
                "Help":"This takes the following parameters
    
    - fs - a remote name string eg "drive:"
    - remote - a path within that remote eg "dir"
    
    See the [purge command](/commands/rclone_purge/) command for more information on the above.",
                "Path":"operations/purge",
                "Title":"Remove a directory or container and all of its contents"
            },
            {
                "AuthRequired":true,
                "Help":"This takes the following parameters
    
    - fs - a remote name string eg "drive:"
    - remote - a path within that remote eg "dir"
    
    See the [rmdir command](/commands/rclone_rmdir/) command for more information on the above.",
                "Path":"operations/rmdir",
                "Title":"Remove an empty directory or container"
            },
            {
                "AuthRequired":true,
                "Help":"This takes the following parameters
    
    - fs - a remote name string eg "drive:"
    - remote - a path within that remote eg "dir"
    - leaveRoot - boolean, set to true not to delete the root
    
    See the [rmdirs command](/commands/rclone_rmdirs/) command for more information on the above.",
                "Path":"operations/rmdirs",
                "Title":"Remove all the empty directories in the path"
            },
            {
                "AuthRequired":true,
                "Help":"This takes the following parameters
    
    - fs - a remote name string eg "drive:path/to/dir"
    
    Returns
    
    - count - number of files
    - bytes - number of bytes in those files
    
    See the [size command](/commands/rclone_size/) command for more information on the above.",
                "Path":"operations/size",
                "Title":"Count the number of bytes and files in remote"
            },
            {
                "AuthRequired":false,
                "Help":"Returns
    - options - a list of the options block names",
                "Path":"options/blocks",
                "Title":"List all the option blocks"
            },
            {
                "AuthRequired":false,
                "Help":"Returns an object where keys are option block names and values are an
    object with the current option values in.
    
    This shows the internal names of the option within rclone which should
    map to the external options very easily with a few exceptions.",
                "Path":"options/get",
                "Title":"Get all the options"
            },
            {
                "AuthRequired":false,
                "Help":"Parameters
    
    - option block name containing an object with
      - key: value
    
    Repeated as often as required.
    
    Only supply the options you wish to change.  If an option is unknown
    it will be silently ignored.  Not all options will have an effect when
    changed like this.
    
    For example:
    
    This sets DEBUG level logs (-vv)
    
        rclone rc options/set --json '{"main": {"LogLevel": 8}}'
    
    And this sets INFO level logs (-v)
    
        rclone rc options/set --json '{"main": {"LogLevel": 7}}'
    
    And this sets NOTICE level logs (normal without -v)
    
        rclone rc options/set --json '{"main": {"LogLevel": 6}}'",
                "Path":"options/set",
                "Title":"Set an option"
            },
            {
                "AuthRequired":false,
                "Help":"This returns an error with the input as part of its error string.
    Useful for testing error handling.",
                "Path":"rc/error",
                "Title":"This returns an error"
            },
            {
                "AuthRequired":false,
                "Help":"This lists all the registered remote control commands as a JSON map in
    the commands response.",
                "Path":"rc/list",
                "Title":"List all the registered remote control commands"
            },
            {
                "AuthRequired":false,
                "Help":"This echoes the input parameters to the output parameters for testing
    purposes.  It can be used to check that rclone is still alive and to
    check that parameter passing is working properly.",
                "Path":"rc/noop",
                "Title":"Echo the input to the output parameters"
            },
            {
                "AuthRequired":true,
                "Help":"This echoes the input parameters to the output parameters for testing
    purposes.  It can be used to check that rclone is still alive and to
    check that parameter passing is working properly.",
                "Path":"rc/noopauth",
                "Title":"Echo the input to the output parameters requiring auth"
            },
            {
                "AuthRequired":true,
                "Help":"This takes the following parameters
    
    - srcFs - a remote name string eg "drive:src" for the source
    - dstFs - a remote name string eg "drive:dst" for the destination
    
    
    See the [copy command](/commands/rclone_copy/) command for more information on the above.",
                "Path":"sync/copy",
                "Title":"copy a directory from source remote to destination remote"
            },
            {
                "AuthRequired":true,
                "Help":"This takes the following parameters
    
    - srcFs - a remote name string eg "drive:src" for the source
    - dstFs - a remote name string eg "drive:dst" for the destination
    - deleteEmptySrcDirs - delete empty src directories if set
    
    
    See the [move command](/commands/rclone_move/) command for more information on the above.",
                "Path":"sync/move",
                "Title":"move a directory from source remote to destination remote"
            },
            {
                "AuthRequired":true,
                "Help":"This takes the following parameters
    
    - srcFs - a remote name string eg "drive:src" for the source
    - dstFs - a remote name string eg "drive:dst" for the destination
    
    
    See the [sync command](/commands/rclone_sync/) command for more information on the above.",
                "Path":"sync/sync",
                "Title":"sync a directory from source remote to destination remote"
            }
        ]
    }
  • 相关阅读:
    摘:SQL Server数据类型的25种
    二维码简介和容错率的问题
    PHP QR Code
    Git 更新操作
    [转载]ecmall语言包程序
    linux 从百度网盘下载文件的方法
    Linux定时备份数据到百度云盘
    nginx整合php+lua+oracle环境搭建
    php 36进制与10进制转换
    “互联网+”取代O2O将成为2016最大风口
  • 原文地址:https://www.cnblogs.com/hahanonym/p/13806851.html
Copyright © 2011-2022 走看看