tanghc 6 years ago
parent ca5855c149
commit d489bdb4ce
  1. 49
      doc/docs/_sidebar.md
  2. 109
      doc/docs/files/10104_文件上传.md
  3. 8
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/FormBodyWrapperFilterExt.java
  4. 8
      sop-common/sop-gateway-common/src/main/java/com/gitee/sop/gatewaycommon/zuul/filter/Servlet30WrapperFilterExt.java
  5. 33
      sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/param/ApiArgumentResolver.java
  6. 38
      sop-common/sop-service-common/src/main/java/com/gitee/sop/servercommon/util/UploadUtil.java
  7. 76
      sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/FileUploadDemoController.java
  8. 10
      sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/param/FileUploadParam.java
  9. 12
      sop-example/sop-story/sop-story-web/src/main/java/com/gitee/sop/storyweb/controller/param/FileUploadParam2.java
  10. 6
      sop-sdk/sdk-csharp/SDKCSharp/Client/OpenClient.cs
  11. 158
      sop-sdk/sdk-csharp/SDKCSharp/Client/OpenHttp.cs
  12. 11
      sop-sdk/sdk-csharp/SDKCSharp/Model/DemoFileUploadModel.cs
  13. 42
      sop-sdk/sdk-csharp/SDKCSharp/Program.cs
  14. 12
      sop-sdk/sdk-csharp/SDKCSharp/Request/BaseRequest.cs
  15. 13
      sop-sdk/sdk-csharp/SDKCSharp/Request/DemoFileUploadRequest.cs
  16. 39
      sop-sdk/sdk-csharp/SDKCSharp/Response/DemoFileUploadResponse.cs
  17. 1
      sop-sdk/sdk-csharp/SDKCSharp/file1.txt
  18. 1
      sop-sdk/sdk-csharp/SDKCSharp/file2.txt
  19. 2
      sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/client/OpenClient.java
  20. 12
      sop-sdk/sdk-java/src/main/java/com/gitee/sop/sdk/request/BaseRequest.java
  21. 2
      sop-sdk/sdk-java/src/main/resources/file1.txt
  22. 2
      sop-sdk/sdk-java/src/main/resources/file2.txt
  23. 8
      sop-sdk/sdk-java/src/test/java/com/gitee/sop/sdk/SdkTest.java

@ -1,26 +1,27 @@
* [首页](/?t=1557833057337)
* [首页](/?t=1557902036067)
* 开发文档
* [快速体验](files/10010_快速体验.md?t=1557833057339)
* [项目接入到SOP](files/10011_项目接入到SOP.md?t=1557833057355)
* [新增接口](files/10020_新增接口.md?t=1557833057355)
* [业务参数校验](files/10030_业务参数校验.md?t=1557833057355)
* [错误处理](files/10040_错误处理.md?t=1557833057355)
* [编写文档](files/10041_编写文档.md?t=1557833057355)
* [接口交互详解](files/10050_接口交互详解.md?t=1557833057355)
* [easyopen支持](files/10070_easyopen支持.md?t=1557833057356)
* [使用签名校验工具](files/10080_使用签名校验工具.md?t=1557833057356)
* [ISV管理](files/10085_ISV管理.md?t=1557833057356)
* [路由授权](files/10090_路由授权.md?t=1557833057356)
* [接口限流](files/10092_接口限流.md?t=1557833057356)
* [SDK开发](files/10095_SDK开发.md?t=1557833057356)
* [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1557833057356)
* [应用授权](files/10097_应用授权.md?t=1557833057356)
* [更改数据节点名称](files/10099_更改数据节点名称.md?t=1557833057356)
* [对接前端](files/10100_对接前端.md?t=1557833057356)
* [自定义过滤器](files/10102_自定义过滤器.md?t=1557833057356)
* [快速体验](files/10010_快速体验.md?t=1557902036070)
* [项目接入到SOP](files/10011_项目接入到SOP.md?t=1557902036086)
* [新增接口](files/10020_新增接口.md?t=1557902036086)
* [业务参数校验](files/10030_业务参数校验.md?t=1557902036086)
* [错误处理](files/10040_错误处理.md?t=1557902036086)
* [编写文档](files/10041_编写文档.md?t=1557902036086)
* [接口交互详解](files/10050_接口交互详解.md?t=1557902036087)
* [easyopen支持](files/10070_easyopen支持.md?t=1557902036087)
* [使用签名校验工具](files/10080_使用签名校验工具.md?t=1557902036087)
* [ISV管理](files/10085_ISV管理.md?t=1557902036087)
* [路由授权](files/10090_路由授权.md?t=1557902036087)
* [接口限流](files/10092_接口限流.md?t=1557902036087)
* [SDK开发](files/10095_SDK开发.md?t=1557902036087)
* [使用SpringCloudGateway](files/10096_使用SpringCloudGateway.md?t=1557902036087)
* [应用授权](files/10097_应用授权.md?t=1557902036087)
* [更改数据节点名称](files/10099_更改数据节点名称.md?t=1557902036087)
* [对接前端](files/10100_对接前端.md?t=1557902036087)
* [自定义过滤器](files/10102_自定义过滤器.md?t=1557902036088)
* [文件上传](files/10104_文件上传.md?t=1557902036088)
* 原理分析
* [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1557833057357)
* [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1557833057357)
* [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1557833057357)
* [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1557833057357)
* [常见问题](files/90100_常见问题.md?t=1557833057357)
* [原理分析之@ApiMapping](files/90010_原理分析之@ApiMapping.md?t=1557902036088)
* [原理分析之路由存储](files/90011_原理分析之路由存储.md?t=1557902036088)
* [原理分析之如何路由](files/90012_原理分析之如何路由.md?t=1557902036088)
* [原理分析之文档归纳](files/90013_原理分析之文档归纳.md?t=1557902036088)
* [常见问题](files/90100_常见问题.md?t=1557902036088)

@ -0,0 +1,109 @@
# 文件上传
请求接口时带上文件
## 客户端调用
```java
DemoFileUploadRequest request = new DemoFileUploadRequest();
DemoFileUploadModel model = new DemoFileUploadModel();
model.setRemark("上传文件参数");
request.setBizModel(model);
List<UploadFile> files = new ArrayList<>();
String root = System.getProperty("user.dir");
System.out.println(root);
// 这里演示将resources下的两个文件上传到服务器
files.add(new UploadFile("file1", new File(root + "/src/main/resources/file1.txt")));
files.add(new UploadFile("file2", new File(root + "/src/main/resources/file2.txt")));
request.setFiles(files);
DemoFileUploadResponse response = client.execute(request);
System.out.println("--------------------");
if (response.isSuccess()) {
List<DemoFileUploadResponse.FileMeta> responseFiles = response.getFiles();
System.out.println("您上传的文件信息:");
responseFiles.stream().forEach(file->{
System.out.println(file);
});
} else {
System.out.println("errorCode:" + response.getCode() + ",errorMsg:" + response.getMsg());
}
System.out.println("--------------------");
```
客户端使用`UploadFile`添加上传文件
```java
/**
* @param name 表单名称,不能重复
* @param file 文件
* @throws IOException
*/
public UploadFile(String name, File file) throws IOException {
this(name, file.getName(), FileUtil.toBytes(file));
}
```
其中`name`表示字段名称,相当于`<input type="file" name="file1"/>`中的name
源码详见sop-sdk
## 服务端接收文件
- 方式1
```java
/**
* 方式1:将文件写在参数中,可直接获取。好处是可以校验是否上传
* @param param
* @return
*/
@ApiMapping(value = "demo.file.upload")
public FileUploadVO file1(FileUploadParam param) {
System.out.println(param.getRemark());
// 获取上传的文件
MultipartFile file1 = param.getFile1();
MultipartFile file2 = param.getFile2();
...
return vo;
}
@Data
public class FileUploadParam {
private String remark;
// 上传文件,字段名称对应表单中的name属性值
@NotNull(message = "文件1不能为空")
private MultipartFile file1;
@NotNull(message = "文件2不能为空")
private MultipartFile file2;
}
```
方式1的好处是可以使用`JSR-303`校验文件是否上传
- 方式2
```java
/**
* 方式2:从request中获取上传文件
*
* @param param
* @return
*/
@ApiMapping(value = "demo.file.upload2")
public FileUploadVO file2(FileUploadParam2 param, HttpServletRequest request) {
System.out.println(param.getRemark());
FileUploadVO vo = new FileUploadVO();
// 获取上传的文件
Collection<MultipartFile> uploadFiles = UploadUtil.getUploadFiles(request);
...
return vo;
}
```
微服务端源码参考`FileUploadDemoController.java`

@ -16,7 +16,11 @@ public class FormBodyWrapperFilterExt extends FormBodyWrapperFilter {
public boolean shouldFilter() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
// 不是上传文件请求,则进行包装
return !RequestUtil.isMultipart(request);
// 如果是文件上传请求,不需要包装
if (RequestUtil.isMultipart(request)) {
return false;
} else {
return super.shouldFilter();
}
}
}

@ -14,7 +14,11 @@ public class Servlet30WrapperFilterExt extends Servlet30WrapperFilter {
public boolean shouldFilter() {
RequestContext ctx = RequestContext.getCurrentContext();
HttpServletRequest request = ctx.getRequest();
// 不是上传文件请求,则进行包装
return !RequestUtil.isMultipart(request);
// 如果是文件上传请求,不需要包装
if (RequestUtil.isMultipart(request)) {
return false;
} else {
return super.shouldFilter();
}
}
}

@ -7,10 +7,13 @@ import com.gitee.sop.servercommon.annotation.ApiMapping;
import com.gitee.sop.servercommon.bean.ParamNames;
import lombok.Data;
import org.springframework.core.MethodParameter;
import org.springframework.util.ReflectionUtils;
import org.springframework.web.bind.support.WebDataBinderFactory;
import org.springframework.web.context.request.NativeWebRequest;
import org.springframework.web.method.support.HandlerMethodArgumentResolver;
import org.springframework.web.method.support.ModelAndViewContainer;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.support.StandardMultipartHttpServletRequest;
import java.util.Map;
@ -49,8 +52,9 @@ public class ApiArgumentResolver implements HandlerMethodArgumentResolver {
protected Object getParamObject(MethodParameter methodParameter, NativeWebRequest nativeWebRequest) {
String bizContent = nativeWebRequest.getParameter(ParamNames.BIZ_CONTENT_NAME);
Class<?> parameterType = methodParameter.getParameterType();
Object bizObj = null;
if (bizContent != null) {
return JSON.parseObject(bizContent, parameterType);
bizObj = JSON.parseObject(bizContent, parameterType);
} else {
Map<String, String[]> parameterMap = nativeWebRequest.getParameterMap();
JSONObject result = new JSONObject();
@ -60,10 +64,33 @@ public class ApiArgumentResolver implements HandlerMethodArgumentResolver {
}
});
if (result.size() > 0) {
return result.toJavaObject(parameterType);
bizObj = result.toJavaObject(parameterType);
}
}
return null;
this.bindUploadFile(bizObj, nativeWebRequest);
return bizObj;
}
/**
* 将文件绑定到
* @param bizObj 业务参数
* @param nativeWebRequest
*/
protected void bindUploadFile(Object bizObj, NativeWebRequest nativeWebRequest) {
if (bizObj == null) {
return;
}
Object nativeRequest = nativeWebRequest.getNativeRequest();
if (nativeRequest instanceof StandardMultipartHttpServletRequest) {
StandardMultipartHttpServletRequest request = (StandardMultipartHttpServletRequest) nativeRequest;
Class<?> bizClass = bizObj.getClass();
ReflectionUtils.doWithFields(bizClass, field -> {
ReflectionUtils.makeAccessible(field);
String name = field.getName();
MultipartFile multipartFile = request.getFile(name);
ReflectionUtils.setField(field, bizObj, multipartFile);
}, field -> field.getType() == MultipartFile.class);
}
}
}

@ -0,0 +1,38 @@
package com.gitee.sop.servercommon.util;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.util.Collection;
import java.util.Collections;
import java.util.Map;
import java.util.Optional;
/**
* 文件上传工具类
*
* @author tanghc
*/
public class UploadUtil {
/**
* 获取上传文件
*
* @param request
* @return
*/
public static Collection<MultipartFile> getUploadFiles(HttpServletRequest request) {
Map<String, MultipartFile> fileMap = null;
//检查form中是否有enctype="multipart/form-data"
if (ServletFileUpload.isMultipartContent(request)) {
//将request变成多部分request
MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
fileMap = multiRequest.getFileMap();
}
return Optional.ofNullable(fileMap)
.map(map -> map.values())
.orElse(Collections.emptyList());
}
}

@ -1,56 +1,78 @@
package com.gitee.sop.storyweb.controller;
import com.gitee.sop.servercommon.annotation.ApiMapping;
import com.gitee.sop.servercommon.util.UploadUtil;
import com.gitee.sop.storyweb.controller.param.FileUploadParam;
import com.gitee.sop.storyweb.controller.param.FileUploadParam2;
import com.gitee.sop.storyweb.vo.FileUploadVO;
import org.apache.commons.fileupload.servlet.ServletFileUpload;
import org.apache.commons.io.IOUtils;
import org.springframework.web.bind.annotation.RestController;
import org.springframework.web.multipart.MultipartFile;
import org.springframework.web.multipart.MultipartHttpServletRequest;
import javax.servlet.http.HttpServletRequest;
import java.io.IOException;
import java.util.Map;
import java.util.Collection;
/**
* 演示文件上传
*
* @author tanghc
*/
@RestController
public class FileUploadDemoController {
/**
* 接收客户端上传的文件然后把文件信息返回给客户端
* 方式1将文件写在参数中可直接获取好处是可以校验是否上传
* @param param
* @param request
* @return
*/
@ApiMapping(value = "demo.file.upload", ignoreValidate = true)
public FileUploadVO file(FileUploadParam param, HttpServletRequest request) {
@ApiMapping(value = "demo.file.upload")
public FileUploadVO file1(FileUploadParam param) {
System.out.println(param.getRemark());
// 获取上传的文件
MultipartFile file1 = param.getFile1();
MultipartFile file2 = param.getFile2();
FileUploadVO vo = new FileUploadVO();
FileUploadVO.FileMeta fileMeta1 = buildFileMeta(file1);
FileUploadVO.FileMeta fileMeta2 = buildFileMeta(file2);
vo.getFiles().add(fileMeta1);
vo.getFiles().add(fileMeta2);
return vo;
}
/**
* 方式2从request中获取上传文件
*
* @param param
* @return
*/
@ApiMapping(value = "demo.file.upload2")
public FileUploadVO file2(FileUploadParam2 param, HttpServletRequest request) {
System.out.println(param.getRemark());
FileUploadVO vo = new FileUploadVO();
//检查form中是否有enctype="multipart/form-data"
if (ServletFileUpload.isMultipartContent(request)) {
//将request变成多部分request
MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest) request;
Map<String, MultipartFile> fileMap = multiRequest.getFileMap();
fileMap.entrySet()
.stream()
.forEach(entry->{
MultipartFile multipartFile = entry.getValue();
try {
String fileName = multipartFile.getOriginalFilename();
long size = multipartFile.getSize();
String fileContent = IOUtils.toString(multipartFile.getInputStream(), "UTF-8");
FileUploadVO.FileMeta fileMeta = new FileUploadVO.FileMeta(fileName, size, fileContent);
vo.getFiles().add(fileMeta);
System.out.println(fileContent);
} catch (IOException e) {
e.printStackTrace();
}
});
// 获取上传的文件
Collection<MultipartFile> uploadFiles = UploadUtil.getUploadFiles(request);
for (MultipartFile multipartFile : uploadFiles) {
FileUploadVO.FileMeta fileMeta = buildFileMeta(multipartFile);
vo.getFiles().add(fileMeta);
}
return vo;
}
private FileUploadVO.FileMeta buildFileMeta(MultipartFile multipartFile) {
// 文件名
String fileName = multipartFile.getOriginalFilename();
// 文件大小
long size = multipartFile.getSize();
// 文件内容
String fileContent = null;
try {
fileContent = IOUtils.toString(multipartFile.getInputStream(), "UTF-8");
} catch (IOException e) {
e.printStackTrace();
}
return new FileUploadVO.FileMeta(fileName, size, fileContent);
}
}

@ -1,6 +1,9 @@
package com.gitee.sop.storyweb.controller.param;
import lombok.Data;
import org.springframework.web.multipart.MultipartFile;
import javax.validation.constraints.NotNull;
/**
* @author tanghc
@ -8,4 +11,11 @@ import lombok.Data;
@Data
public class FileUploadParam {
private String remark;
// 上传文件,字段名称对应表单中的name属性值
@NotNull(message = "文件1不能为空")
private MultipartFile file1;
@NotNull(message = "文件2不能为空")
private MultipartFile file2;
}

@ -0,0 +1,12 @@
package com.gitee.sop.storyweb.controller.param;
import lombok.Data;
/**
* @author tanghc
*/
@Data
public class FileUploadParam2 {
private String remark;
}

@ -21,6 +21,7 @@ namespace SDKCSharp.Client
{
private static OpenConfig DEFAULT_CONFIG = new OpenConfig();
private const String ERROR_RESPONSE_KEY = "error_response";
private Dictionary<string, string> header = new Dictionary<string, string>();
@ -137,6 +138,11 @@ namespace SDKCSharp.Client
string method = request.Method;
string dataName = this.dataNameBuilder.Build(method);
Dictionary<string, object> jsonObject = JsonUtil.ParseToDictionary(resp);
bool errorResponse = jsonObject.ContainsKey(ERROR_RESPONSE_KEY);
if (errorResponse)
{
dataName = ERROR_RESPONSE_KEY;
}
object data = jsonObject[dataName];
string jsonData = data == null ? "{}" : data.ToString();
T t = JsonUtil.ParseObject<T>(jsonData);

@ -131,6 +131,7 @@ namespace SDKCSharp.Client
}
}
/// <summary>
/// post请求,并且文件上传
/// </summary>
@ -141,77 +142,126 @@ namespace SDKCSharp.Client
/// <returns></returns>
public string PostFile(string url, Dictionary<string, string> form, Dictionary<string, string> header, List<UploadFile> files)
{
Encoding ENCODING_UTF8 = Encoding.UTF8;
using (MemoryStream memoryStream = new MemoryStream())
HttpWebRequest request = CreateWebRequest(url, header);
request.Method = METHOD_POST;
// 分隔符
string boundary = "----" + DateTime.Now.Ticks.ToString("x");
request.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
// 请求流
var postStream = new MemoryStream();
#region 处理Form表单请求内容
// 文件数据模板
string fileFormdataTemplate =
"\r\n--" + boundary +
"\r\nContent-Disposition: form-data; name=\"{0}\"; filename=\"{1}\"" +
"\r\nContent-Type: application/octet-stream" +
"\r\n\r\n";
// 文本数据模板
string dataFormdataTemplate =
"\r\n--" + boundary +
"\r\nContent-Disposition: form-data; name=\"{0}\"" +
"\r\n\r\n{1}";
// 是否有上传文件
bool hasFile = files != null && files.Count > 0;
if (hasFile)
{
// 1.分界线
string boundary = string.Format("----{0}", DateTime.Now.Ticks.ToString("x")), // 分界线可以自定义参数
appendBoundary = string.Format("--{0}\r\n", boundary),
endBoundary = string.Format("\r\n--{0}--\r\n", boundary);
byte[] beginBoundaryBytes = ENCODING_UTF8.GetBytes(appendBoundary),
endBoundaryBytes = ENCODING_UTF8.GetBytes(endBoundary);
StringBuilder payload = new StringBuilder();
// 2.组装 上传文件附加携带的参数 到内存流中
if (form != null && form.Count > 0)
// 处理上传文件
foreach (var fileItem in files)
{
ICollection<string> keys = form.Keys;
foreach (string key in keys)
string formdata = null;
// 上传文件
formdata = string.Format(
fileFormdataTemplate,
fileItem.Name, //表单键
fileItem.FileName);
byte[] formdataBytes = null;
// 第一行不需要换行
if (postStream.Length == 0)
{
string boundaryBlock = string.Format("{0}Content-Disposition: form-data; name=\"{1}\"\r\n\r\n{2}\r\n", appendBoundary, key, form[key]);
byte[] boundaryBlockBytes = ENCODING_UTF8.GetBytes(boundaryBlock);
memoryStream.Write(boundaryBlockBytes, 0, boundaryBlockBytes.Length);
formdataBytes = Encoding.UTF8.GetBytes(formdata.Substring(2, formdata.Length - 2));
}
}
else
{
formdataBytes = Encoding.UTF8.GetBytes(formdata);
}
postStream.Write(formdataBytes, 0, formdataBytes.Length);
// 3.组装文件头数据体 到内存流中
foreach (UploadFile uploadFile in files)
// 写入文件内容
if (fileItem.FileData != null && fileItem.FileData.Length > 0)
{
postStream.Write(fileItem.FileData, 0, fileItem.FileData.Length);
}
}
}
// 处理文本字段
foreach (var fieldItem in form)
{
string formdata = null;
{
string boundaryBlock = string.Format("{0}Content-Disposition: form-data; name=\"{1}\"; filename=\"{2}\"\r\nContent-Type: application/octet-stream\r\n\r\n", appendBoundary, uploadFile.Name, uploadFile.FileName);
byte[] boundaryBlockBytes = ENCODING_UTF8.GetBytes(boundaryBlock);
memoryStream.Write(boundaryBlockBytes, 0, boundaryBlockBytes.Length);
memoryStream.Write(uploadFile.FileData, 0, uploadFile.FileData.Length);
// 上传文本
formdata = string.Format(
dataFormdataTemplate,
fieldItem.Key,
fieldItem.Value);
}
// 4.组装结束分界线数据体 到内存流中
memoryStream.Write(endBoundaryBytes, 0, endBoundaryBytes.Length);
// 5.获取二进制数据,最终需要发送给服务器的数据
byte[] postBytes = memoryStream.ToArray();
// 6.HttpWebRequest 组装
HttpWebRequest webRequest = CreateWebRequest(url, header);
webRequest.Method = METHOD_POST;
webRequest.ContentType = string.Format("multipart/form-data; boundary={0}", boundary);
webRequest.ContentLength = postBytes.Length;
BindHeader(webRequest, header);
if (Regex.IsMatch(url, "^https://"))
byte[] formdataBytes = null;
// 第一行不需要换行
if (postStream.Length == 0)
{
ServicePointManager.SecurityProtocol = SecurityProtocolType.Tls;
ServicePointManager.ServerCertificateValidationCallback = CheckValidationResult;
formdataBytes = Encoding.UTF8.GetBytes(formdata.Substring(2, formdata.Length - 2));
}
// 7.写入上传请求数据
using (Stream requestStream = webRequest.GetRequestStream())
else
{
requestStream.Write(postBytes, 0, postBytes.Length);
formdataBytes = Encoding.UTF8.GetBytes(formdata);
}
// 8.获取响应
using (HttpWebResponse webResponse = (HttpWebResponse)webRequest.GetResponse())
postStream.Write(formdataBytes, 0, formdataBytes.Length);
}
// 结尾
var footer = Encoding.UTF8.GetBytes("\r\n--" + boundary + "--\r\n");
postStream.Write(footer, 0, footer.Length);
#endregion
request.ContentLength = postStream.Length;
#region 输入二进制流
if (postStream != null)
{
postStream.Position = 0;
// 直接写入流
Stream requestStream = request.GetRequestStream();
byte[] buffer = new byte[1024];
int bytesRead = 0;
while ((bytesRead = postStream.Read(buffer, 0, buffer.Length)) != 0)
{
using (StreamReader reader = new StreamReader(webResponse.GetResponseStream(), ENCODING_UTF8))
{
string body = reader.ReadToEnd();
return body;
}
requestStream.Write(buffer, 0, bytesRead);
}
////debug
//postStream.Seek(0, SeekOrigin.Begin);
//StreamReader sr = new StreamReader(postStream);
//var postStr = sr.ReadToEnd();
postStream.Close();//关闭文件访问
}
#endregion
HttpWebResponse response = (HttpWebResponse)request.GetResponse();
if (cookieContainer != null)
{
response.Cookies = cookieContainer.GetCookies(response.ResponseUri);
}
using (Stream responseStream = response.GetResponseStream())
{
using (StreamReader myStreamReader = new StreamReader(responseStream, Encoding.UTF8))
{
return myStreamReader.ReadToEnd();
}
}
}
static bool CheckValidationResult(object sender, X509Certificate certificate, X509Chain chain, SslPolicyErrors errors)

@ -0,0 +1,11 @@
using System;
using Newtonsoft.Json;
namespace SDKCSharp.Model
{
public class DemoFileUploadModel
{
[JsonProperty("remark")]
public string Remark { get; set; }
}
}

@ -1,6 +1,7 @@
using System;
using System.Collections;
using System.Collections.Generic;
using System.IO;
using SDKCSharp.Client;
using SDKCSharp.Common;
using SDKCSharp.Model;
@ -27,8 +28,9 @@ namespace SDKTest
public static void Main(string[] args)
{
TestGet();
TestCommon();
//TestGet();
//TestCommon();
TestUpload();
}
// 标准用法
@ -90,5 +92,41 @@ namespace SDKTest
response.Code, response.Msg, response.SubCode, response.SubMsg);
}
}
private static void TestUpload()
{
DemoFileUploadRequest request = new DemoFileUploadRequest();
DemoFileUploadModel model = new DemoFileUploadModel
{
Remark = "上传文件参数"
};
request.BizModel = model;
string root = Environment.CurrentDirectory;
Console.WriteLine("当前目录{0}", root);
// 文件上传
// 将当前目录下的两个文件上传到服务器
request.AddFile(new UploadFile("file1", root + "/file1.txt"));
request.AddFile(new UploadFile("file2", root + "/file2.txt"));
DemoFileUploadResponse response = client.Execute(request);
if (response.IsSuccess())
{
List<DemoFileUploadResponse.FileMeta> responseFiles = response.Files;
Console.WriteLine("您上传的文件信息:");
responseFiles.ForEach(file =>
{
Console.WriteLine("上传的文件名:{0},文件大小:{1},文件内容:{2}", file.Filename, file.Size, file.Content);
}
);
}
else
{
Console.WriteLine("错误, code:{0}, msg:{1}, subCode:{2}, subMsg:{3}",
response.Code, response.Msg, response.SubCode, response.SubMsg);
}
}
}
}

@ -60,6 +60,18 @@ namespace SDKCSharp.Request
this.version = version == null ? SdkConfig.DEFAULT_VERSION : version;
}
/// <summary>
/// 添加上传文件
/// </summary>
/// <param name="file">File.</param>
public void AddFile(UploadFile file)
{
if(this.files == null)
{
this.files = new List<UploadFile>();
}
this.files.Add(file);
}
/// <summary>
/// 创建请求表单

@ -0,0 +1,13 @@
using System;
using SDKCSharp.Response;
namespace SDKCSharp.Request
{
public class DemoFileUploadRequest : BaseRequest<DemoFileUploadResponse>
{
public override string GetMethod()
{
return "demo.file.upload";
}
}
}

@ -0,0 +1,39 @@
using System;
using System.Collections;
using System.Collections.Generic;
using Newtonsoft.Json;
namespace SDKCSharp.Response
{
public class DemoFileUploadResponse : BaseResponse
{
[JsonProperty("files")]
private List<FileMeta> files = new List<FileMeta>();
public List<FileMeta> Files { get => files; set => files = value; }
public class FileMeta
{
public FileMeta(String filename, long size, String content)
{
this.Filename = filename;
this.Size = size;
this.Content = content;
}
public FileMeta()
{
}
[JsonProperty("filename")]
public String Filename { get; set; }
[JsonProperty("size")]
public long Size { get; set; }
[JsonProperty("content")]
public String Content { get; set; }
}
}
}

@ -0,0 +1 @@
file1 content,内容1

@ -0,0 +1 @@
file2 content,内容2

@ -25,7 +25,7 @@ public class OpenClient {
private static final Log log = LogFactory.getLog(OpenClient.class);
private static final OpenConfig DEFAULT_CONFIG = new OpenConfig();
public static final String ERROR_RESPONSE_KEY = "error_response";
private static final String ERROR_RESPONSE_KEY = "error_response";
private String url;
private String appId;

@ -9,6 +9,7 @@ import com.gitee.sop.sdk.response.BaseResponse;
import com.gitee.sop.sdk.util.ClassUtil;
import java.text.SimpleDateFormat;
import java.util.ArrayList;
import java.util.Date;
import java.util.HashMap;
import java.util.List;
@ -71,6 +72,17 @@ public abstract class BaseRequest<T extends BaseResponse> {
return SdkConfig.DEFAULT_VERSION;
}
/**
* 添加上传文件
* @param file
*/
public void addFile(UploadFile file) {
if (this.files == null) {
this.files = new ArrayList<>();
}
this.files.add(file);
}
public RequestForm createRequestForm(OpenConfig openConfig) {
// 公共请求参数
Map<String, String> params = new HashMap<String, String>();

@ -1 +1 @@
file1 content
file1 content,内容1

@ -1 +1 @@
file2 content...
file2 content,内容2

@ -17,7 +17,6 @@ import org.junit.Test;
import java.io.File;
import java.io.IOException;
import java.util.ArrayList;
import java.util.HashMap;
import java.util.List;
import java.util.Map;
@ -87,12 +86,11 @@ public class SdkTest extends TestCase {
model.setRemark("上传文件参数");
request.setBizModel(model);
List<UploadFile> files = new ArrayList<>();
String root = System.getProperty("user.dir");
System.out.println(root);
files.add(new UploadFile("file1", new File(root + "/src/main/resources/file1.txt")));
files.add(new UploadFile("file2", new File(root + "/src/main/resources/file2.txt")));
request.setFiles(files);
// 这里演示将resources下的两个文件上传到服务器
request.addFile(new UploadFile("file1", new File(root + "/src/main/resources/file1.txt")));
request.addFile(new UploadFile("file2", new File(root + "/src/main/resources/file2.txt")));
DemoFileUploadResponse response = client.execute(request);

Loading…
Cancel
Save