使用HttpWebRequest附加携带请求参数以post方式模拟上传大文件(以图片为例)到Web服务器端

实现图片上传http-request // 页面结构 <el-upload class="avatar-uploader" :action="uploadUrl" :http-request="upload" :show-file-list="false" :before-upload="beforeUpload" list-type="picture-card" > <img v-if="addSizeForm.siteLogo" :src="addSizeForm.sizeLogo" class="avata 阅读详情

一、Http协议上传文件(以图片为例)请求报文体内容格式

首先,我们来看下通过浏览器上传文件的请求报文内容格式,这里以本人自己写的实例为例,如下图。除了能上传图片(即:头像字段),还携带了用户名、密码两个字段,很好的诠释了http带参数上传文件的情形。点击提交按钮后,浏览器会将文件(即头像文件)二进制数据和用户名、密码以post方式发送至服务器。这时我们可以通过抓包工具(如:fiddler)(或者浏览器自带的开发者工具F12)查看请求报文内容。

HttpWebRequest携带参数上传图片等大文件

通过抓包工具获取到携带参数上传文件请求报文体内容格式如下:

POST /PostUploadHandler.ashx HTTP/1.1
Host: localhost:44187
Connection: keep-alive
Content-Length: 19839
Cache-Control: max-age=0
Accept: text/html,application/xhtml+xml,application/xml;q=0.9,image/webp,*/*;q=0.8
Origin: http://localhost:44187
Upgrade-Insecure-Requests: 1
User-Agent: Mozilla/5.0 (Windows NT 6.1; WOW64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/45.0.2454.101 Safari/537.36
Content-Type: multipart/form-data; boundary=----WebKitFormBoundaryNSF3vGLxKBlk5kcB
Referer: http://localhost:44187/UploadDemo.aspx
Accept-Encoding: gzip, deflate
Accept-Language: zh-CN,zh;q=0.8
 
 
------WebKitFormBoundaryNSF3vGLxKBlk5kcB
Content-Disposition: form-data; name="userName"
 
admin
------WebKitFormBoundaryNSF3vGLxKBlk5kcB
Content-Disposition: form-data; name="userPwd"
 
123456
------WebKitFormBoundaryNSF3vGLxKBlk5kcB
Content-Disposition: form-data; name="photo"; filename="1.png"
Content-Type: image/png
 
<!--这一行是文件二进制数据-->
------WebKitFormBoundaryNSF3vGLxKBlk5kcB--

1、请求头中有一个Content-Type参数(默认值:application/x-www-form-urlencoded),其中multipart/form-data值表示向服务器发送二进制数据,boundary表示请求体的分界线,服务器就是依靠分界线分割请求体来读取数据,此参数值可自定义。

2、请求体依靠boundary有规则的排列参数。每一行字符串后面包含一个换行符“\r\n”,有一个开始分界线(--boundary)和一个结束分界线(--boundary--),参数与参数之间通过--boundary分离,每一个参数的键(key)和值(value)之间包含一个空行即:“\r\n"。

二、完整版HttpWebRequest模拟上传文件请求报文内容封装

通过上面介绍,我们已经清楚了解了http协议上传文件的POST请求报文内容格式,在.net中使用HttpWebRequest上传文件,我们只要按照此格式封装请求报文,即可实现携带参数上传功能了。

为了方便扩展和维护,把所有请求参数(如上传地址url、携带参数、上传文件流等)封装到一个类中,代码如下:

/// <summary>
/// 上传文件 - 请求参数类
/// </summary>
public class UploadParameterType
{
    public UploadParameterType()
    {
        FileNameKey = "fileName";
        Encoding = Encoding.UTF8;
        PostParameters = new Dictionary<string, string>();
    }
    /// <summary>
    /// 上传地址
    /// </summary>
    public string Url { get; set; }
    /// <summary>
    /// 文件名称key
    /// </summary>
    public string FileNameKey { get; set; }
    /// <summary>
    /// 文件名称value
    /// </summary>
    public string FileNameValue { get; set; }
    /// <summary>
    /// 编码格式
    /// </summary>
    public Encoding Encoding { get; set; }
    /// <summary>
    /// 上传文件的流
    /// </summary>
    public Stream UploadStream { get; set; }
    /// <summary>
    /// 上传文件 携带的参数集合
    /// </summary>
    public IDictionary<string, string> PostParameters { get; set; } 
}

新建一个上传文件工具类(命名为:HttpUploadClient),在类中增加上传方法(命名为:Execute),如下所示:

/// <summary>
/// Http上传文件类 - HttpWebRequest封装
/// </summary>
public class HttpUploadClient
{
    /// <summary>
    /// 上传执行 方法
    /// </summary>
    /// <param name="parameter">上传文件请求参数</param>
    public static string Execute(UploadParameterType parameter)
    {
         
    }
    static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
    {
        return true;
    }
}

Post上传请求体参数是二进制格式的,我们只需要将参数根据以上报文体内容格式拼接好数据,存放在内存流里面,拼接完整后,将整个内存流转换成二进制格式写入到HttpWebRequest请求体中就行,下面我们来一步一步的拼接报文体内容。

1、定义开始结束分界线boundary及拼接开始分界线:

public static string Execute(UploadParameterType parameter)
{
    using (MemoryStream memoryStream = new MemoryStream())
    {
        // 1.分界线
        string boundary = string.Format("----{0}", DateTime.Now.Ticks.ToString("x")),       // 分界线可以自定义参数
            beginBoundary = string.Format("--{0}\r\n", boundary),
            endBoundary = string.Format("\r\n--{0}--\r\n", boundary);
        byte[] beginBoundaryBytes = parameter.Encoding.GetBytes(beginBoundary),
            endBoundaryBytes = parameter.Encoding.GetBytes(endBoundary);
        // 2.组装开始分界线数据体 到内存流中
        memoryStream.Write(beginBoundaryBytes, 0, beginBoundaryBytes.Length);
        // ……
    }
}

2、拼接附加携带参数:

// 3.组装 上传文件附加携带的参数 到内存流中
if (parameter.PostParameters != null && parameter.PostParameters.Count > 0)
{
    foreach (KeyValuePair<string, string> keyValuePair in parameter.PostParameters)
    {
        string parameterHeaderTemplate = string.Format("Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}\r\n{2}", keyValuePair.Key, keyValuePair.Value, beginBoundary);
        byte[] parameterHeaderBytes = parameter.Encoding.GetBytes(parameterHeaderTemplate);
 
        memoryStream.Write(parameterHeaderBytes, 0, parameterHeaderBytes.Length);
    }
}

3、拼接上传文件体及结束分界线boundary(需要注意的是Content-Type的值是:application/octet-stream):

// 4.组装文件头数据体 到内存流中
string fileHeaderTemplate = string.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: application/octet-stream\r\n\r\n", parameter.FileNameKey, parameter.FileNameValue);
byte[] fileHeaderBytes = parameter.Encoding.GetBytes(fileHeaderTemplate);
memoryStream.Write(fileHeaderBytes, 0, fileHeaderBytes.Length);
// 5.组装文件流 到内存流中
byte[] buffer = new byte[1024 * 1024 * 1];
int size = parameter.UploadStream.Read(buffer, 0, buffer.Length);
while (size > 0)
{
    memoryStream.Write(buffer, 0, size);
    size = parameter.UploadStream.Read(buffer, 0, buffer.Length);
}
// 6.组装结束分界线数据体 到内存流中
memoryStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);

4、通过以上步骤,上传文件请求体内容数据已经拼接完成,接下来就是对HttpWebRequest对象的属性设置(如:请求地址Url,请求方法Method,Content-Type等),把整个上传文件请求体内存流写入到HttpWebRequest对象的请求体中,然后发起上传请求。如下源码:

// 7.获取二进制数据
byte[] postBytes = memoryStream.ToArray();
// 8.HttpWebRequest 组装
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(new Uri(parameter.Url, UriKind.RelativeOrAbsolute));
webRequest.Method = "POST";
webRequest.Timeout = 10000;
webRequest.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
webRequest.ContentLength = postBytes.Length;
if (Regex.IsMatch(parameter.Url, "^https://"))
{
    ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
    ServicePointManager.ServerCertificateValidationCallback = CheckValidationResult;
}
// 9.写入上传请求数据
using (Stream requestStream = webRequest.GetRequestStream())
{
    requestStream.Write(postBytes, 0, postBytes.Length);
    requestStream.Close();
}
// 10.获取响应
using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
{
    using (StreamReader reader = new StreamReader(webResponse.GetResponseStream(), parameter.Encoding))
    {
        string body = reader.ReadToEnd();
        reader.Close();
        return body;
    }
}

完整版HttpWebRequest模拟上传文件代码如下:

/// <summary>
/// Http上传文件类 - HttpWebRequest封装
/// </summary>
public class HttpUploadClient
{
    /// <summary>
    /// 上传执行 方法
    /// </summary>
    /// <param name="parameter">上传文件请求参数</param>
    public static string Execute(UploadParameterType parameter)
    {
        using (MemoryStream memoryStream = new MemoryStream())
        {
            // 1.分界线
            string boundary = string.Format("----{0}", DateTime.Now.Ticks.ToString("x")),       // 分界线可以自定义参数
                beginBoundary = string.Format("--{0}\r\n", boundary),
                endBoundary = string.Format("\r\n--{0}--\r\n", boundary);
            byte[] beginBoundaryBytes = parameter.Encoding.GetBytes(beginBoundary),
                endBoundaryBytes = parameter.Encoding.GetBytes(endBoundary);
            // 2.组装开始分界线数据体 到内存流中
            memoryStream.Write(beginBoundaryBytes, 0, beginBoundaryBytes.Length);
            // 3.组装 上传文件附加携带的参数 到内存流中
            if (parameter.PostParameters != null && parameter.PostParameters.Count > 0)
            {
                foreach (KeyValuePair<string, string> keyValuePair in parameter.PostParameters)
                {
                    string parameterHeaderTemplate = string.Format("Content-Disposition: form-data; name=\"{0}\"\r\n\r\n{1}\r\n{2}", keyValuePair.Key, keyValuePair.Value, beginBoundary);
                    byte[] parameterHeaderBytes = parameter.Encoding.GetBytes(parameterHeaderTemplate);
 
                    memoryStream.Write(parameterHeaderBytes, 0, parameterHeaderBytes.Length);
                }
            }
            // 4.组装文件头数据体 到内存流中
            string fileHeaderTemplate = string.Format("Content-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"\r\nContent-Type: application/octet-stream\r\n\r\n", parameter.FileNameKey, parameter.FileNameValue);
            byte[] fileHeaderBytes = parameter.Encoding.GetBytes(fileHeaderTemplate);
            memoryStream.Write(fileHeaderBytes, 0, fileHeaderBytes.Length);
            // 5.组装文件流 到内存流中
            byte[] buffer = new byte[1024 * 1024 * 1];
            int size = parameter.UploadStream.Read(buffer, 0, buffer.Length);
            while (size > 0)
            {
                memoryStream.Write(buffer, 0, size);
                size = parameter.UploadStream.Read(buffer, 0, buffer.Length);
            }
            // 6.组装结束分界线数据体 到内存流中
            memoryStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
            // 7.获取二进制数据
            byte[] postBytes = memoryStream.ToArray();
            // 8.HttpWebRequest 组装
            HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(new Uri(parameter.Url, UriKind.RelativeOrAbsolute));
            webRequest.Method = "POST";
            webRequest.Timeout = 10000;
            webRequest.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
            webRequest.ContentLength = postBytes.Length;
            if (Regex.IsMatch(parameter.Url, "^https://"))
            {
                ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
                ServicePointManager.ServerCertificateValidationCallback = CheckValidationResult;
            }
            // 9.写入上传请求数据
            using (Stream requestStream = webRequest.GetRequestStream())
            {
                requestStream.Write(postBytes, 0, postBytes.Length);
                requestStream.Close();
            }
            // 10.获取响应
            using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
            {
                using (StreamReader reader = new StreamReader(webResponse.GetResponseStream(), parameter.Encoding))
                {
                    string body = reader.ReadToEnd();
                    reader.Close();
                    return body;
                }
            }
        }
    }
    static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)
    {
        return true;
    }
}

为了验证封装是否正确,可以写一个控制台应用程序来模拟Http协议上传文件(以图片为例),结果如图:

三、asp.net(c#)使用HttpWebRequest携带请求参数模拟上传文件封装源码下载

HttpWebRequest模拟上传文件封装源码

C#模拟POST提交表单(二)--HttpWebRequest以及HttpWebResponse 上次介绍了用WebClient的方式提交POST请求,这次,我继续来介绍用其它一种方式 HttpWebRequest以及HttpWebResponse 自认为与上次介绍的WebClient最大的不同之处在于HttpWebRequest更灵活,也更强大,比如,HttpWebRequest支持Cookie,而WebClient就不支持,因此,如果要登录某个网站才能进行某些操作的时候,Htt 阅读详情

相关推荐

C# HttpWebRequest详解

一.前言 HttpWebRequest是C#原生语法提供的实现了Http协议完整封装的类,可以实现任意类型的Http请求。但是也因为参数众多,导致很多人不容易掌握它。 今天我们来尝试从简入繁的给大家介绍下HttpWebRequest 二.常用属性 AllowAutoRedirect:获取或设置一个值,该值指示请求是否应跟随重定向响应。 CookieContainer:获取或设置与此请求关联的cookie。 Credentials:获取或设置请求的身份验证信息。 KeepAlive:获取或设置

TxNet 3万+

HttpWebRequest发送数据 post

1、创建HttpWebRequest对象 HttpWebRequest对象用WebRequest.Create(url)方法获得。 2、初始化HttpWebRequest对象(设置http请求常用属性) 3、附加Post给服务器的数据到HttpWebRequest对象(写入HttpWebRequest对象提供的一个stream里面) 4、读取服务器的返回信息(注意返回数据的Encod...

weixin_34390996的博客 515

Http方式实现图片上传

学习笔记,通过Http方式实现固定路径下的图片上传,本资源只是Android代码,不含服务器端代码。

Unity C# 之 使用 HttpWebRequest 基础知识/HttpWebRequest 进行异步Post 网络访问/数据流形式获取数据(Task/async/await)的代码简单实现

可以使用 UnityWebRequest 访问,不过好似只能用协程的方式,并且访问只能在主线程中;所以这里使用 C# 中的 HttpWebRequest,进行网络访问,而且 HttpWebRequest,允许在子线程中访问,在一些情况下可以大大减少主线程的网络访问压力;这里使用 HttpWebRequest ,进行 Post 访问,并且Task 结合 async (await) 的进行异步访问,最后使用 Stream 流式的形式获取数据,在这里做一个简单的记录,以便后期使用的时候参考。

仙魁XAN 8424

舵机PWM信号转互斥继电器开关信号

-----------------本文由“麦粒电子”撰写,并提供相应产品服务。---------------- 叙述 上次的PWM转继电器开关方案得到大家的不少好评(博客链接),但是发现有些玩家需要一路PWM同时去控制两路继电器开关通断,并且两者是互斥的,好去控制两种不同的负载。所以就继续升级了如下的模块。 正常的控制部件顺序这样:遥控器按钮拨动,遥控器接收机相应通道PWM值变化,PWM转开关模块检测PWM值发生变化从而驱动相应机械继电器触点吸合释放。本模块的两个继电器动作是互斥的,也就是不会同时吸合。

Mai_LiElectronic的博客 1627

避开ANSYS SOLID65钢筋模拟的坑:从材料TB到实常数R的完整配置清单

本文详细解析了ANSYS SOLID65单元在钢筋混凝土模拟中的关键配置与优化技巧,涵盖材料TB设置、实常数R配置及收敛性优化。特别针对钢筋建模的分布式钢筋模型进行深度解析,提供实战验证的参数设置手册,帮助工程师避免常见错误,提升模拟精度与效率。

weixin_30898555的博客 362

【转】asp.net(c#)使用HttpWebRequest附加携带请求参数以post方式模拟上传大文件(以图片为例)到Web服务器端...

原文地址:http://docode.top/Article/Detail/10002 目录: 1、Http协议上传文件(以图片为例)请求报文体内容格式 2、完整版HttpWebRequest模拟上传文件请求报文内容封装 3、asp.net(c#)使用HttpWebRequest携带请求参数模拟上传文件封装源码下载 一、Http协议上传文件(以图片为例)请求报文体内容格式 首先...

weixin_34014555的博客 530

Silvaco Atlas入门指南——从零开始掌握半导体器件仿真

本文为Silvaco Atlas半导体器件仿真软件的入门指南,详细介绍了从零开始掌握该工具的核心流程。内容涵盖Atlas的基本概念、仿真流程、核心文件(输入、结构、输出文件)、交互式与批处理两种操作模式,并逐步演示了如何从定义网格、划分区域、设置电极到进行掺杂、选择物理模型并求解,最终获取和分析器件特性的完整步骤。旨在帮助微电子相关专业人员和工程师快速上手这一强大的“数字实验室”,提升半导体器件设计与研发效率。

weixin_29306317的博客 398

asp.net(c#)使用HttpWebRequest附加携带请求参数以post方式模拟上传大文件(以图片为例)到Web服务器端

原文链接:http://www.cnblogs.com/GodX/archive/2016/06/21/5604944.html

zhruifei的专栏 1189

手把手教你用 Docker 构建自己的 CentOS 基础镜像

目录一、准备CentOS基础镜像二、撰写Dockerfile三、构建Docker镜像四、生成Docker容器 相信码农们经常会听说:虚拟机将成为历史,Docker才是未来 !!! 事实如此,现在大部分公司都在用 Docker 技术,想拥有自己的 Docker 专属镜像,那么 Dockerfile 就是入门,现在让我们一起来看一下 ------ 构建 Docker 镜像的全过程。 好文章 记得收藏...

Nick.Peng's Blogs 1万+

R数据分析:广义估计方程式GEE的做法和解释

好久没有更新文章了,因为同学们咨询的问题有点多,另一个原因就是自己实在太懒。。。。 今天继续给大家写广义估计方程式GEE。 In statistics, a generalized estimating equation (GEE) is used to estimate the parameters of a generalized linear model with a possible unknown correlation between outcomes. 上面的英文解释告诉我们,当我们

Codewar的博客 1万+

HttpWebRequest上传图片Post到接口

1.对照Fiddler  Post图片的方式,例如上传2张图片在fiddler中是这样的格式 ---------------------------acebdf13572468 Content-Disposition: form-data; name="file"; filename="Chrysanthemum.jpg" Content-Type: application/octet-st

yindubing的专栏 4658

把静态前端托管进 SAP BTP:HTML5 Application Deployer 与企业级内容部署全攻略

本文介绍了在SAP BTP Cloud Foundry环境中使用HTML5 Application Repository托管前端静态资源的工程化实践。通过HTML5 Application Deployer工具,结合MTA描述、路由配置和服务实例,实现前后端解耦和标准化部署。文章详细阐述了目录结构、关键配置文件、MTA编排以及构建部署流程,并针对大体积前端资源提供了GACD和异步上传两种解决方案。最后说明了如何与AppRouter协同工作,使部署内容可供终端用户访问。这套方法使前端更新无需重启后端,支持团队

2007 年 ~ 2025 年,深耕 SAP 技术 18 年 154

Windows Phone 使用 HttpWebRequest 对象,通过POST 方式上传图片

Windows Phone 客户端有时候需要把用户的图片保存到服务器端。本示例讲解如果把用户的头像,通过表单传输的方式,把用户的 头像传递到 Web 端。当前的工程选择的是 OS7.1,在 WP8上通用,但需要注意的一点是,当前测试工程的 Web 端的地址是回环地址: localhost,所以如果在 WP8 的模拟器或者真机中测试时,需要真实 IP 地址,并且需要进行一些 ...

weixin_30426065的博客 146

(考研湖科大教书匠计算机网络)第四章网络层-第三节3、4:划分子网的IPv4地址和无分类IP地址

子网掩码: 32比特的子网掩码可以表明分类IP地址的主机号部分被借用了几个比特作为子网号子网掩码使用连续的比特1来对应网络号和子网号子网掩码使用连续的比特0来对应主机号将划分子网的IPv4地址与其相应的子网掩码进行逻辑与运算就可得到IPv4地址所在子网的网络地址如下图。

快乐江湖的博客 1343

Unity零基础到进阶 | Unity Shader 深度硬核解析

Unity Shader 是运行在GPU上的可编程渲染程序,是整个引擎渲染体系的算法核心。它通过 Unity 封装的 ShaderLab 语法 + GPU 原生 HLSL 语言编写,定义了「网格数据如何经过光照计算、纹理采样、几何变换、混合测试,最终转化为屏幕像素颜色」的完整规则。 通俗来说:Shader 决定物体「怎么画」,材质(Material)只是 Shader 的参数实例,决定「用什么画」。没有 Shader,材质就是无渲染能力的空壳;没有材质,Shader 无法落地到具体物体。

努力前行,总会成为自己心中的那道光 1万+

C#模拟POST提交表单--HttpWebRequest以及HttpWebResponse

上次介绍了用WebClient的方式提交POST请求,这次,我继续来介绍用其它一种方式 HttpWebRequest以及HttpWebResponse 自认为与上次介绍的WebClient最大的不同之处在于HttpWebRequest更灵活,也更强大,比如,HttpWebRequest支持Cookie,而WebClient就不支持,因此,如果要登录某个网站才能进行某些操作的

786

怀旧版电脑GBC模拟器

再现原版GBC掌机的界面,电脑运行连游戏界面都一样大小,很怀旧,很真实,(英文版)强烈推荐,很小的文件,很难才找到的。

HttpWebRequest模拟登陆(附带验证码)

///           /// 通过get方式请求页面,传递一个实例化的cookieContainer           ///           ///           ///           ///           public static ArrayList GetHtmlData(string postUrl, Cooki

Dylan_csdn的专栏 700

VC中sqlite的使用

在VC中对sqlite的使用,实现数据库大批数据的快速插入,读取数据库中的数据在ListCtrl中显示

VB摄像头监控

该VB模块可对摄像头捕获的画面进行录像等,可在创建的窗口进行控制

艾伟_转载:尝试通过HttpWebRequest向TAOBAO批量发布商品及上传图片

  朋友开了个淘宝店,所以经常要将新商品及图片发布到网店里,而且有时还需要上传很多商品。如果手工一条一个商品的上传未免太花时间,所以我就琢磨着能否用WinForm写个程序通过WebRequest发送POST/GET请求来达到这个目的。由于上传上品时即有普通的Form字段信息需要提交,还需要上传图片,所以在写HttpWebRequest时参考了这个帖子http://bytes.com/topic/c...

weixin_34232363的博客 220

最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版

Part-E1-SDIO-Specification-Ver4.00-Final-120220.pdf:最新的sdio 4.0 spec 协议标准 带书签 高清完整PDF版,包括SDIO 接口的外设,SDIO 接口官方协议等。

C# 利用 HttpWebRequest 和 HttpWebResponse 模拟登录有验证码的网站

我们经常会碰到需要程序模拟登录一个网站,那如果网站需要填写验证码的要怎样模拟登录呢? 这篇文章利用了 HttpWebRequest 和 HttpWebResponse 模拟登录了有验证码的网站。 程序设计的界面很简单,三个TextBox分别输入用户名、密码和验证码,一个Image控件显示从网站请求到的验证码图片,还有两个按钮,一个换验证码,一个登录。 写程序前,先用浏览器的开发者工具观察

6154
上一篇: NET中对url字符串中域名的三种截取方式
下一篇: Windows 系统中的文件路径格式
.NET跨平台
博客等级 码龄15年 6066粉丝 738原创
评论
成就一亿技术人!
拼手气红包6.0元
还能输入1000个字符
 
 条评论被折叠 查看
添加红包

请填写红包祝福语或标题

个

红包个数最小为10个

元

红包金额最低5元

当前余额3.43元 前往充值 >
需支付:10.00元
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付元
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值