精华内容
下载资源
问答
  • java实现postman中form-data传参方式
    展开全文
  • Postman请求如下: Java方法编码如下: /** * 以post方式调用第三方接口,以form-data 形式 发送数据 * * @param url post请求url * @param paramMap 表单里其他参数 * @return */ public static String doPost...

       目前在做一个JavaWeb的开发工作,前端传过来的参数是Json格式,但下一级服务要求数据格式为form表单。
       查看网上的写法,多次尝试均存在问题,故给出如下解决方案,希望能给小伙伴们一个参考。
    Postman请求如下:
    在这里插入图片描述
    Java方法编码如下:

    /**
         * 以post方式调用第三方接口,以form-data 形式  发送数据
         *
         * @param url  post请求url
         * @param paramMap 表单里其他参数
         * @return
         */
        public static String doPost(String url, Map<String, String> paramMap) {
            // 创建Http实例
            CloseableHttpClient httpClient = HttpClients.createDefault();
            // 创建HttpPost实例
            HttpPost httpPost = new HttpPost(url);       
            try {
                MultipartEntityBuilder builder = MultipartEntityBuilder.create();
                builder.setCharset(java.nio.charset.Charset.forName("UTF-8"));
                builder.setMode(HttpMultipartMode.BROWSER_COMPATIBLE);
                
                //表单中参数
               for(Map.Entry<String, String> entry: paramMap.entrySet()) {
                    builder.addPart(entry.getKey(),new StringBody(entry.getValue(), ContentType.create("text/plain", Consts.UTF_8)));
                }
               
                HttpEntity entity = builder.build();
                httpPost.setEntity(entity);
                HttpResponse response = httpClient.execute(httpPost);// 执行提交
                          
                if (response.getStatusLine().getStatusCode() == HttpStatus.SC_OK) {
                    // 返回
                    String res = EntityUtils.toString(response.getEntity(), java.nio.charset.Charset.forName("UTF-8"));
                    return res;
                }
               
            } catch (Exception e) {
                e.printStackTrace();
                logger.error("调用HttpPost失败!" + e.toString());
            } finally {
                if (httpClient != null) {
                    try {
                        httpClient.close();
                    } catch (IOException e) {
                        logger.error("关闭HttpPost连接失败!");
                    }
                }
            }       
            return null;              
        }
    
    展开全文
  • postman中几种传参方式区别: 1.form-data form-data主要是以键值对的形式来上传参数,同时参数之间以&分隔符分开,同时也可以上传文件,文件上传要指定文件类型,具体可以看下面的图。 2.x-...

    postman中几种传参方式区别:
    1.form-data
    form-data主要是以键值对的形式来上传参数,同时参数之间以&分隔符分开,同时也可以上传文件,文件上传要指定文件类型,具体可以看下面的图。

    2.x-www-form-urlencode
    这种参数的传递与form-data最大的区别是,x-www-form-urlencode只能是以键值对的形式传参,不能上传文件。

    3.raw
    这个比较强大,可以上传任意格式文件,具体的可以上传text文本文件、json文件、xml文件、html文件等。

    4.binary
    这种只能上传二进制文件,就是通常所说的文本文件。具体可以参见下图。

    然后上次在用java实现一个向后台传参的形式时,在postman里以form-data的形式传参,我就尝试利用map进行数据的的封装Map<String,String>,结果发现后台无法正确解析参数。是因为map封装后并不是以&链接的。需要传递的参数和参数形式如下所示:

    利用spring来作为后端框架,form-data利用LinkedMultiValueMap对象来包装多个参数,参数以key-value形式,中间以&连接。利用java代码的实现如下:

    public ResponseData baseApi(String args,String bizContent){
            if(args == null || args.equals("")){
                ResponseData responseData = new ResponseData(false,"the param methodArg is null","");
                return responseData;
            }
            if(bizContent == null || bizContent.equals("")){
                ResponseData responseData = new ResponseData(false,"the param bizContent is null","");
                return responseData;
            }
                String apiUrl = Contants.publicUrl  +"/"+ args;
                HttpHeaders headers = new HttpHeaders();
                MultiValueMap<String, String> map= new LinkedMultiValueMap<>();
                headers.setContentType(MediaType.APPLICATION_FORM_URLENCODED);
                map.add("app_id", Contants.clientId);
                map.add("method",args);
                map.add("format","json");
                map.add("charset","utf-8");
                map.add("timestamp",Contants.timeStamp);
                map.add("token",Contants.accessToken);
                map.add("biz_content",bizContent);
                HttpEntity<MultiValueMap<String, String>> requestParams = new HttpEntity<>(map, headers);
                ResponseEntity<String> response = restTemplate.postForEntity(apiUrl,requestParams,String.class);
                String result =response.getBody();
                JSONObject jsStr = JSONObject.parseObject(result);
                String resultCode = jsStr.getString("code");
    
                if(Integer.parseInt(resultCode)!= 0){
                    ResponseData responseData = new ResponseData(false,"error",result);
                    return responseData;
                }
    
                ResponseData responseData = new ResponseData(true,"success",result);
                return responseData;
        }

    Http post 发送 multipart/form-data 格式数据-Java 实现

    package awesome.data.structure.http;
    
    
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    
    import java.io.*;
    import java.net.HttpURLConnection;
    import java.net.URL;
    import java.util.HashMap;
    import java.util.Map;
    
    /**
     * http 工具类
     *
     * @author: 
     * @time: 2019/9/9 17:09
     * @since
     */
    public class HttpUtils {
        private static final Logger LOGGER = LoggerFactory.getLogger(HttpUtils.class);
        /**
         * multipart/form-data 格式发送数据时各个部分分隔符的前缀,必须为 --
         */
        private static final String BOUNDARY_PREFIX = "--";
        /**
         * 回车换行,用于一行的结尾
         */
        private static final String LINE_END = "\r\n";
    
        /**
         * post 请求:以表单方式提交数据
         * <p>
         * 由于 multipart/form-data 不是 http 标准内容,而是属于扩展类型,
         * 因此需要自己构造数据结构,具体如下:
         * <p>
         * 1、首先,设置 Content-Type
         * <p>
         * Content-Type: multipart/form-data; boundary=${bound}
         * <p>
         * 其中${bound} 是一个占位符,代表我们规定的分割符,可以自己任意规定,
         * 但为了避免和正常文本重复了,尽量要使用复杂一点的内容
         * <p>
         * 2、设置主体内容
         * <p>
         * --${bound}
         * Content-Disposition: form-data; name="userName"
         * <p>
         * Andy
         * --${bound}
         * Content-Disposition: form-data; name="file"; filename="测试.excel"
         * Content-Type: application/octet-stream
         * <p>
         * 文件内容
         * --${bound}--
         * <p>
         * 其中${bound}是之前头信息中的分隔符,如果头信息中规定是123,那这里也要是123;
         * 可以很容易看到,这个请求提是多个相同部分组成的:
         * 每一部分都是以--加分隔符开始的,然后是该部分内容的描述信息,然后一个回车换行,然后是描述信息的具体内容;
         * 如果传送的内容是一个文件的话,那么还会包含文件名信息以及文件内容类型。
         * 上面第二部分是一个文件体的结构,最后以--分隔符--结尾,表示请求体结束
         *
         * @param urlStr      请求的url
         * @param filePathMap key 参数名,value 文件的路径
         * @param keyValues   普通参数的键值对
         * @param headers
         * @return
         * @throws IOException
         */
        public static HttpResponse postFormData(String urlStr, Map<String, String> filePathMap, Map<String, Object> keyValues, Map<String, Object> headers) throws IOException {
            HttpResponse response;
            HttpURLConnection conn = getHttpURLConnection(urlStr, headers);
            //分隔符,可以任意设置,这里设置为 MyBoundary+ 时间戳(尽量复杂点,避免和正文重复)
            String boundary = "MyBoundary" + System.currentTimeMillis();
            //设置 Content-Type 为 multipart/form-data; boundary=${boundary}
            conn.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + boundary);
    
            //发送参数数据
            try (DataOutputStream out = new DataOutputStream(conn.getOutputStream())) {
                //发送普通参数
                if (keyValues != null && !keyValues.isEmpty()) {
                    for (Map.Entry<String, Object> entry : keyValues.entrySet()) {
                        writeSimpleFormField(boundary, out, entry);
                    }
                }
                //发送文件类型参数
                if (filePathMap != null && !filePathMap.isEmpty()) {
                    for (Map.Entry<String, String> filePath : filePathMap.entrySet()) {
                        writeFile(filePath.getKey(), filePath.getValue(), boundary, out);
                    }
                }
    
                //写结尾的分隔符--${boundary}--,然后回车换行
                String endStr = BOUNDARY_PREFIX + boundary + BOUNDARY_PREFIX + LINE_END;
                out.write(endStr.getBytes());
            } catch (Exception e) {
                LOGGER.error("HttpUtils.postFormData 请求异常!", e);
                response = new HttpResponse(500, e.getMessage());
                return response;
            }
    
            return getHttpResponse(conn);
        }
    
        /**
         * 获得连接对象
         *
         * @param urlStr
         * @param headers
         * @return
         * @throws IOException
         */
        private static HttpURLConnection getHttpURLConnection(String urlStr, Map<String, Object> headers) throws IOException {
            URL url = new URL(urlStr);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            //设置超时时间
            conn.setConnectTimeout(50000);
            conn.setReadTimeout(50000);
            //允许输入流
            conn.setDoInput(true);
            //允许输出流
            conn.setDoOutput(true);
            //不允许使用缓存
            conn.setUseCaches(false);
            //请求方式
            conn.setRequestMethod("POST");
            //设置编码 utf-8
            conn.setRequestProperty("Charset", "UTF-8");
            //设置为长连接
            conn.setRequestProperty("connection", "keep-alive");
    
            //设置其他自定义 headers
            if (headers != null && !headers.isEmpty()) {
                for (Map.Entry<String, Object> header : headers.entrySet()) {
                    conn.setRequestProperty(header.getKey(), header.getValue().toString());
                }
            }
    
            return conn;
        }
    
        private static HttpResponse getHttpResponse(HttpURLConnection conn) {
            HttpResponse response;
            try (BufferedReader reader = new BufferedReader(new InputStreamReader(conn.getInputStream()))) {
                int responseCode = conn.getResponseCode();
                StringBuilder responseContent = new StringBuilder();
                String line;
                while ((line = reader.readLine()) != null) {
                    responseContent.append(line);
                }
                response = new HttpResponse(responseCode, responseContent.toString());
            } catch (Exception e) {
                LOGGER.error("获取 HTTP 响应异常!", e);
                response = new HttpResponse(500, e.getMessage());
            }
            return response;
        }
    
        /**
         * 写文件类型的表单参数
         *
         * @param paramName 参数名
         * @param filePath  文件路径
         * @param boundary  分隔符
         * @param out
         * @throws IOException
         */
        private static void writeFile(String paramName, String filePath, String boundary,
                                      DataOutputStream out) {
            try (BufferedReader fileReader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath)))) {
                /**
                 * 写分隔符--${boundary},并回车换行
                 */
                String boundaryStr = BOUNDARY_PREFIX + boundary + LINE_END;
                out.write(boundaryStr.getBytes());
                /**
                 * 写描述信息(文件名设置为上传文件的文件名):
                 * 写 Content-Disposition: form-data; name="参数名"; filename="文件名",并回车换行
                 * 写 Content-Type: application/octet-stream,并两个回车换行
                 */
                String fileName = new File(filePath).getName();
                String contentDispositionStr = String.format("Content-Disposition: form-data; name=\"%s\"; filename=\"%s\"", paramName, fileName) + LINE_END;
                out.write(contentDispositionStr.getBytes());
                String contentType = "Content-Type: application/octet-stream" + LINE_END + LINE_END;
                out.write(contentType.getBytes());
    
                String line;
                while ((line = fileReader.readLine()) != null) {
                    out.write(line.getBytes());
                }
                //回车换行
                out.write(LINE_END.getBytes());
            } catch (Exception e) {
                LOGGER.error("写文件类型的表单参数异常", e);
            }
        }
    
        /**
         * 写普通的表单参数
         *
         * @param boundary 分隔符
         * @param out
         * @param entry    参数的键值对
         * @throws IOException
         */
        private static void writeSimpleFormField(String boundary, DataOutputStream out, Map.Entry<String, Object> entry) throws IOException {
            //写分隔符--${boundary},并回车换行
            String boundaryStr = BOUNDARY_PREFIX + boundary + LINE_END;
            out.write(boundaryStr.getBytes());
            //写描述信息:Content-Disposition: form-data; name="参数名",并两个回车换行
            String contentDispositionStr = String.format("Content-Disposition: form-data; name=\"%s\"", entry.getKey()) + LINE_END + LINE_END;
            out.write(contentDispositionStr.getBytes());
            //写具体内容:参数值,并回车换行
            String valueStr = entry.getValue().toString() + LINE_END;
            out.write(valueStr.getBytes());
        }
    
        public static void main(String[] args) throws IOException {
            //请求 url
            String url = "http://127.0.0.1:8080/settlement/createTaskSettlement";
    
            // keyValues 保存普通参数
            Map<String, Object> keyValues = new HashMap<>();
            String taskDescription = "众包测试";
            String taskExpiredTime = "2019-09-12";
            String taskRequirement = "1";
            String taskTitle = "测试测试啊";
            keyValues.put("task_description", taskDescription);
            keyValues.put("task_expired_time", taskExpiredTime);
            keyValues.put("task_requirement", taskRequirement);
            keyValues.put("task_title", taskTitle);
    
            // filePathMap 保存文件类型的参数名和文件路径
            Map<String, String> filePathMap = new HashMap<>();
            String paramName = "file";
            String filePath = "C:\\Users\\magos\\Downloads\\Andy测试模板001.xlsx";
            filePathMap.put(paramName, filePath);
    
            //headers
            Map<String, Object> headers = new HashMap<>();
            //COOKIE: Name=Value;Name2=Value2
            headers.put("COOKIE", "token=OUFFNzQ0OUU5RDc1ODM0Q0M3QUM5NzdENThEN0Q1NkVEMjhGNzJGNEVGRTNCN0JEODM5NzAyNkI0OEE0MDcxNUZCMjdGNUMxMzdGRUE4MTcwRjVDNkJBRTE2ODgzQURDRjNCQjdBMTdCODc0MzA4QzFFRjlBQkM1MTA0N0MzMUU=");
    
            HttpResponse response = postFormData(url, filePathMap, keyValues, headers);
            System.out.println(response);
    
        }
    
        /**
         * 发送文本内容
         *
         * @param urlStr
         * @param filePath
         * @return
         * @throws IOException
         */
        public static HttpResponse postText(String urlStr, String filePath) throws IOException {
            HttpResponse response;
            URL url = new URL(urlStr);
            HttpURLConnection conn = (HttpURLConnection) url.openConnection();
            conn.setRequestMethod("POST");
            conn.setRequestProperty("Content-Type", "text/plain");
            conn.setDoOutput(true);
            conn.setConnectTimeout(5000);
            conn.setReadTimeout(5000);
    
            try (BufferedWriter writer = new BufferedWriter(new OutputStreamWriter(conn.getOutputStream()));
                 BufferedReader fileReader = new BufferedReader(new InputStreamReader(new FileInputStream(filePath)))) {
                String line;
                while ((line = fileReader.readLine()) != null) {
                    writer.write(line);
                }
    
            } catch (Exception e) {
                LOGGER.error("HttpUtils.postText 请求异常!", e);
                response = new HttpResponse(500, e.getMessage());
                return response;
            }
    
            return getHttpResponse(conn);
        }
    }
    
    
    package awesome.data.structure.http;
    
    /**
     * @author:  
     * @time: 2019/7/10 14:41
     * @since
     */
    public class HttpResponse {
        private int code;
        private String content;
    
        public HttpResponse(int status, String content) {
            this.code = status;
            this.content = content;
        }
    
        public int getCode() {
            return code;
        }
    
        public void setCode(int code) {
            this.code = code;
        }
    
        public String getContent() {
            return content;
        }
    
        public void setContent(String content) {
            this.content = content;
        }
    
        public String toString(){
            return new StringBuilder("[ code = ").append(code)
                    .append(" , content = ").append(content).append(" ]").toString();
        }
    }
    
    
    
    

     Spring Boot 文件上传与下载

    参数配置

    项目创建完成之后,需要设置一些必要的参数,打开项目resources目录下配置文件application.properties,在其中添加以下参数:

     

    server.port=80
    
    ## MULTIPART (MultipartProperties)
    # 开启 multipart 上传功能
    spring.servlet.multipart.enabled=true
    # 文件写入磁盘的阈值
    spring.servlet.multipart.file-size-threshold=2KB
    # 最大文件大小
    spring.servlet.multipart.max-file-size=200MB
    # 最大请求大小
    spring.servlet.multipart.max-request-size=215MB
    
    ## 文件存储所需参数
    # 所有通过 REST APIs 上传的文件都将存储在此目录下
    file.upload-dir=./uploads
    

    其中file.upload-dir=./uploads参数为自定义的参数,创建FileProperties.javaPOJO类,使配置参数可以自动绑定到POJO类。

     

    import org.springframework.boot.context.properties.ConfigurationProperties;
    
    @ConfigurationProperties(prefix = "file")
    public class FileProperties {
        private String uploadDir;
    
        public String getUploadDir() {
            return uploadDir;
        }
        public void setUploadDir(String uploadDir) {
            this.uploadDir = uploadDir;
        }
    }
    

    然后在@SpringBootApplication注解的类中添加@EnableConfigurationProperties注解以开启ConfigurationProperties功能。

    SpringBootFileApplication.java

     

    @SpringBootApplication
    @EnableConfigurationProperties({
            FileProperties.class
    })
    public class SpringBootFileApplication {
    
        public static void main(String[] args) {
            SpringApplication.run(SpringBootFileApplication.class, args);
        }
    }
    

    配置完成,以后若有file前缀开头的参数需要配置,可直接在application.properties配置文件中配置并更新FileProperties.java即可。

    另外再创建一个上传文件成功之后的Response响应实体类UploadFileResponse.java及异常类FileException.java来处理异常信息。

    UploadFileResponse.java

     

    public class UploadFileResponse {
        private String fileName;
        private String fileDownloadUri;
        private String fileType;
        private long size;
    
        public UploadFileResponse(String fileName, String fileDownloadUri, String fileType, long size) {
            this.fileName = fileName;
            this.fileDownloadUri = fileDownloadUri;
            this.fileType = fileType;
            this.size = size;
        }
        // getter and setter ...
    }
    

    FileException.java

     

    public class FileException extends RuntimeException{
        public FileException(String message) {
            super(message);
        }
    
        public FileException(String message, Throwable cause) {
            super(message, cause);
        }
    }
    

    创建接口

    下面需要创建文件上传下载所需的 REST APIs 接口。创建文件FileController.java

     

    import com.james.sample.file.dto.UploadFileResponse;
    import com.james.sample.file.service.FileService;
    import org.slf4j.Logger;
    import org.slf4j.LoggerFactory;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.core.io.Resource;
    import org.springframework.http.HttpHeaders;
    import org.springframework.http.MediaType;
    import org.springframework.http.ResponseEntity;
    import org.springframework.web.bind.annotation.*;
    import org.springframework.web.multipart.MultipartFile;
    import org.springframework.web.servlet.support.ServletUriComponentsBuilder;
    
    import javax.servlet.http.HttpServletRequest;
    import java.io.IOException;
    import java.util.Arrays;
    import java.util.List;
    import java.util.stream.Collectors;
    
    @RestController
    public class FileController {
    
        private static final Logger logger = LoggerFactory.getLogger(FileController.class);
    
        @Autowired
        private FileService fileService;
    
        @PostMapping("/uploadFile")
        public UploadFileResponse uploadFile(@RequestParam("file") MultipartFile file){
            String fileName = fileService.storeFile(file);
    
            String fileDownloadUri = ServletUriComponentsBuilder.fromCurrentContextPath()
                    .path("/downloadFile/")
                    .path(fileName)
                    .toUriString();
    
            return new UploadFileResponse(fileName, fileDownloadUri,
                    file.getContentType(), file.getSize());
        }
    
    
        @PostMapping("/uploadMultipleFiles")
        public List<UploadFileResponse> uploadMultipleFiles(@RequestParam("files") MultipartFile[] files) {
            return Arrays.stream(files)
                    .map(this::uploadFile)
                    .collect(Collectors.toList());
        }
    
        @GetMapping("/downloadFile/{fileName:.+}")
        public ResponseEntity<Resource> downloadFile(@PathVariable String fileName, HttpServletRequest request) {
            // Load file as Resource
            Resource resource = fileService.loadFileAsResource(fileName);
    
            // Try to determine file's content type
            String contentType = null;
            try {
                contentType = request.getServletContext().getMimeType(resource.getFile().getAbsolutePath());
            } catch (IOException ex) {
                logger.info("Could not determine file type.");
            }
    
            // Fallback to the default content type if type could not be determined
            if(contentType == null) {
                contentType = "application/octet-stream";
            }
    
            return ResponseEntity.ok()
                    .contentType(MediaType.parseMediaType(contentType))
                    .header(HttpHeaders.CONTENT_DISPOSITION, "attachment; filename=\"" + resource.getFilename() + "\"")
                    .body(resource);
        }
    }
    

    FileController类在接收到用户的请求后,使用FileService类提供的storeFile()方法将文件写入到系统中进行存储,其存储目录就是之前在application.properties配置文件中的file.upload-dir参数的值./uploads

    下载接口downloadFile()在接收到用户请求之后,使用FileService类提供的loadFileAsResource()方法获取存储在系统中文件并返回文件供用户下载。

    FileService.java

     

    import com.james.sample.file.exception.FileException;
    import com.james.sample.file.property.FileProperties;
    import org.springframework.beans.factory.annotation.Autowired;
    import org.springframework.core.io.Resource;
    import org.springframework.core.io.UrlResource;
    import org.springframework.stereotype.Service;
    import org.springframework.util.StringUtils;
    import org.springframework.web.multipart.MultipartFile;
    
    import java.io.IOException;
    import java.net.MalformedURLException;
    import java.nio.file.Files;
    import java.nio.file.Path;
    import java.nio.file.Paths;
    import java.nio.file.StandardCopyOption;
    
    @Service
    public class FileService {
    
        private final Path fileStorageLocation; // 文件在本地存储的地址
    
        @Autowired
        public FileService(FileProperties fileProperties) {
            this.fileStorageLocation = Paths.get(fileProperties.getUploadDir()).toAbsolutePath().normalize();
            try {
                Files.createDirectories(this.fileStorageLocation);
            } catch (Exception ex) {
                throw new FileException("Could not create the directory where the uploaded files will be stored.", ex);
            }
        }
    
        /**
         * 存储文件到系统
         *
         * @param file 文件
         * @return 文件名
         */
        public String storeFile(MultipartFile file) {
            // Normalize file name
            String fileName = StringUtils.cleanPath(file.getOriginalFilename());
    
            try {
                // Check if the file's name contains invalid characters
                if(fileName.contains("..")) {
                    throw new FileException("Sorry! Filename contains invalid path sequence " + fileName);
                }
    
                // Copy file to the target location (Replacing existing file with the same name)
                Path targetLocation = this.fileStorageLocation.resolve(fileName);
                Files.copy(file.getInputStream(), targetLocation, StandardCopyOption.REPLACE_EXISTING);
    
                return fileName;
            } catch (IOException ex) {
                throw new FileException("Could not store file " + fileName + ". Please try again!", ex);
            }
        }
    
        /**
         * 加载文件
         * @param fileName 文件名
         * @return 文件
         */
        public Resource loadFileAsResource(String fileName) {
            try {
                Path filePath = this.fileStorageLocation.resolve(fileName).normalize();
                Resource resource = new UrlResource(filePath.toUri());
                if(resource.exists()) {
                    return resource;
                } else {
                    throw new FileException("File not found " + fileName);
                }
            } catch (MalformedURLException ex) {
                throw new FileException("File not found " + fileName, ex);
            }
        }
    }
    

    接口测试

    在完成上述的代码之后,打开SpringBootFileApplication.java并运行,运行完成之后就可以使用 Postman 进行测试了。

    单个文件上传结果:

     

    多个文件上传结果:

     

     参照: https://github.com/JemGeek/spring-boot-sample/tree/master/spring-boot-file-upload


    Spring Cloud Feign的文件上传实现

    服务提供方(接收文件)

    服务提供方的实现比较简单,就按Spring MVC的正常实现方式即可,比如:

     

    @EnableFeignClients
    @EnableDiscoveryClient
    @SpringBootApplication
    public class Application {
    
        @RestController
        public class UploadController {
    
            @PostMapping(value = "/uploadFile", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
            public String handleFileUpload(@RequestPart(value = "file") MultipartFile file) {
                return file.getName();
            }
    
        }
    
        public static void main(String[] args) {
            new SpringApplicationBuilder(Application.class).web(true).run(args);
        }
    
    }
    

    feign调用接口 注解中加入配置类

    @FeignClient(value = "xxx", configuration = FeignMultipartSupportConfig.class)
    public interface IUploadService {
        /**
         * 文件上传
         * @param file 文件
         * @return
         */
        @RequestMapping(value = "upload/uppic", method = RequestMethod.POST, consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
        ResultModel<String> uppic(@RequestPart(value = "file")MultipartFile file, @RequestParam Map<String,Object> map);
    
    }

     

    服务消费方(发送文件)

    在服务消费方由于会使用Feign客户端,所以在这里需要在引入feign对表单提交的依赖,具体如下:

     

    <dependency>
       <groupId>io.github.openfeign.form</groupId>
       <artifactId>feign-form</artifactId>
       <version>3.0.3</version>
    </dependency>
    <dependency>
       <groupId>io.github.openfeign.form</groupId>
       <artifactId>feign-form-spring</artifactId>
       <version>3.0.3</version>
    </dependency>
    <dependency>
       <groupId>commons-fileupload</groupId>
       <artifactId>commons-fileupload</artifactId>
       <version>1.3.3</version>
    </dependency>
    

    定义文件上传方的应用主类和FeignClient,假设服务提供方的服务名为eureka-feign-upload-server

     

    @EnableFeignClients
    @EnableDiscoveryClient
    @SpringBootApplication
    public class Application {
    
        public static void main(String[] args) {
            new SpringApplicationBuilder(Application.class).web(true).run(args);
        }
    
    }
    
    @FeignClient(value = "upload-server", configuration = UploadService.MultipartSupportConfig.class)
    public interface UploadService {
     
        @PostMapping(value = "/uploadFile", consumes = MediaType.MULTIPART_FORM_DATA_VALUE)
        String handleFileUpload(@RequestPart(value = "file") MultipartFile file);
     
        @Configuration
        class MultipartSupportConfig {
            @Bean
            public Encoder feignFormEncoder() {
                return new SpringFormEncoder();
            }
        }
     
    }
    

    在启动了服务提供方之后,尝试在服务消费方编写测试用例来通过上面定义的Feign客户端来传文件,比如:

     

    @Slf4j
    @RunWith(SpringJUnit4ClassRunner.class)
    @SpringBootTest
    public class UploadTester {
    
        @Autowired
        private UploadService uploadService;
    
        @Test
        @SneakyThrows
        public void testHandleFileUpload() {
    
            File file = new File("upload.txt");
            DiskFileItem fileItem = (DiskFileItem) new DiskFileItemFactory().createItem("file",
                    MediaType.TEXT_PLAIN_VALUE, true, file.getName());
    
            try (InputStream input = new FileInputStream(file); OutputStream os = fileItem.getOutputStream()) {
                IOUtils.copy(input, os);
            } catch (Exception e) {
                throw new IllegalArgumentException("Invalid file: " + e, e);
            }
    
            MultipartFile multi = new CommonsMultipartFile(fileItem);
    
            log.info(uploadService.handleFileUpload(multi));
        }
    
    }
    

    @RequestParam与@RequestPart的区别

     

    RequestParam:请求参数到处理器功能处理方法的方法参数上的绑定;
    @RequestPart:提供对“multipart/form-data”请求的全面支持,支持Servlet 3.0文件上传(javax.servlet.http.Part)、支持内容的HttpMessageConverter(即根据请求头的Content-Type,来判断内容区数据是什么类型,如JSON、XML,能自动转换为命令对象),比@RequestParam更强大(只能对请求参数数据绑定,key-alue格式),而@RequestPart支持如JSON、XML内容区数据的绑定;
    

    完整示例:

    读者可以根据喜好选择下面的两个仓库中查看eureka-feign-upload-servereureka-feign-upload-client两个项目:

     

     

     

    展开全文
  • 1. Java实现Postman功能 public OceanusResponseDTO<JSONObject> doApi(String rootUrl, Api api, JSONObject post) { StringBuffer strBf = new StringBuffer(); try { URL realUrl = new URL(rootUrl+api...

    1. Java实现Postman功能

    public OceanusResponseDTO<JSONObject> doApi(String rootUrl, Api api, JSONObject post) {
            StringBuffer strBf = new StringBuffer();
            try {
                URL realUrl = new URL(rootUrl+api.getUrl());
                HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
                connection.setDoOutput(true);
                connection.setDoInput(true);
                connection.setRequestMethod("POST");
                connection.setUseCaches(false);
                connection.setInstanceFollowRedirects(true);
                connection.setRequestProperty("Content-Type", "application/json;charset=utf-8");
                connection.connect();
                DataOutputStream dataout = new DataOutputStream(connection.getOutputStream());
                String query = post.toString();
                //System.out.println(query); //能正常显示数据
                dataout.write(query.getBytes("UTF-8"));
                dataout.flush();
                dataout.close();
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
                String lines;
                while ((lines = reader.readLine()) != null) {
                    lines = new String(lines.getBytes(), "utf-8");
                    strBf.append(lines);
                }
                reader.close();
                connection.disconnect();
                System.out.println("返回数据:"+strBf.toString());
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
    

    2.重点知识讲解

    2.1 URL请求类型

    URL请求的类别,分为GET和POST请求。二者区别是:
    1)GET请求是把参数放在URL字串后,传递给servlet
    2)POST请求是把参数放在http请求的正文内。一般是String字符串

    2.2 URLConnection对象问题

    URL realUrl = new URL(rootUrl+api.getUrl());
    HttpURLConnection connection = (HttpURLConnection) realUrl.openConnection();
    

    这里realUrl打开URL连接,实则是生成HttpURLConnection对象,故可以直接转换为HttpURLConnection对象,以便使用更多的API

    2.3 connection的连接问题

    //设置是否向httpURLConnection输出,因为这个是post请求,参数要放在http正文内,故设为true
    connection.setDoOutput(true);
    //设置是否从httpURlConnection读入,默认情况下是true
    connection.setDoInput(true);
    //设置post请求
    connection.setRequestMethod("POST");
    //post请求不能使用缓存
    connection.setUseCaches(false);
    //设置httpURLConnection实例是否自动执行重定向
    connection.setInstanceFollowRedirects(true);
    //设置请求头里面的各个属性
    connection.setRequestProperty("Content-Type", "application/json;charset=utf-8"); 
    //建立连接
    connection.connect();
    

    2.4 URLConnection发送数据和接收数据问题

    			//创建输入输出流,用于 向连接里面 输出 携带的参数 (输出内容为 连接?后面的内容)
                DataOutputStream dataout = new DataOutputStream(connection.getOutputStream());
                String query = post.toString();
                //将参数输出到连接
                dataout.write(query.getBytes("UTF-8"));
                //输出完成后刷新并关闭流
                dataout.flush();
                //重要步骤 勿忘
                dataout.close();  
                //读取输出的流
                BufferedReader reader = new BufferedReader(new InputStreamReader(connection.getInputStream(), "UTF-8"));
                String lines;
                //将读取的数据保存到lines这个字符串
                while ((lines = reader.readLine()) != null) {
                    lines = new String(lines.getBytes(), "utf-8");
                    strBf.append(lines);
                }
                //关闭流
                reader.close();
                //关闭连接
                connection.disconnect();
                //打印数据
                System.out.println("返回数据:"+strBf.toString());
            } catch (Exception e) {
                e.printStackTrace();
            }
            return null;
    
    展开全文
  • 1 概述Postman是一款测试rest接口的工具,可以实现前端未实施的情况下,后端同步开发。本文从部署到运用进行展开描写。2 部署第一步:进入Postman官网下载最新版本,下载链接第二步:版本安装,启动截面如下所示:3 ...
  • 笔者使用:postman软件来调试post请求,很好用本文主要讲的是:Java实现HttpPost请求,需要传输参数,有可能需要传输json格式参数所需要的jar包获取地址:点击此处(不一定是最新版本,但亲测有效)下面的代码是实例...
  • 2、基于java的区块链系统开发 (1)开发环境 (2)区块链模型构建 (3)共识机制实现 (4)P2P网络开发 (5)系统测试 3、源代码与参考文献 (1)本文完整源代码地址 (2)参考书籍 (3)参考资料1、区块链技术常见架构目前主流的...
  • 今天实现一个导出模板的功能,踩了一个坑 我在功能完成之后,使用postman的导出下载功能进行测试,如下图: 我明明设置了导出的文件名,但是一直导出response.xls,这个就很是奇怪了. 最后我在地址栏进行测试了...
  • 项目的框架是springCloud 的一个服务,图片上传实际上就是用java的IO 流进行读写文件,给后台传递一个路径,后台通过浏览器链接到前端,将前端的图片数据拷贝的服务器的存储地址。1. 服务端保存图片的地址:...
  • 一、Postman参数化通过前面的代码,发现每次登陆的时候都会重新生成token,如果测试用例比较多的话,每次都要重新输入token,就会很麻烦;PostMan给我们提供了参数功能的参数化(以下) 1、设置PostMan-Environment...
  • 今天尝试了一下分析12306网站的余票查询接口,实现12306余票查询功能。 1.查找并分析余票查询API接口 笔者的查询的是2019-09-04广州到驻马店的车票信息,ajax请求地址为: ...leftTicketDTO...
  •  Postman是一款测试rest接口的工具,可以实现前端未实施的情况下,后端同步开发。本文从部署到运用进行展开描写。 2 部署 第一步:进入Postman官网下载最新版本,下载链接 第二步:版本安装,启动截面如下所示:...
  • java实现商品信息的录入,查找,修改,删除的接口 一、四步构建项目 第一步:打开idea,点击文件,接着点项目 第二步: 第三步: 第四步: 二、构建目录文件 目录如下: 三、重点编写代码: 在pom....
  • java实现树形菜单

    2020-09-28 12:58:37
    java实现树形菜单遇到问题 问题描述: 简单使用递归结构实现菜单创建,postman测试始终500.逻辑没有发现问题 List<Menu> childList = new ArrayList<>(); for(Menu menu:menus){ if(menu....
  • 1、命令行执行脚本的最基本的命令newman runxxx.json 2、生成html格式的报告先安装插件:npm install -g newman-reporter-htmlnewmanrundemo.postman_collection.json -r html 3、优化报告显示格式,生成美观一点的...
  • 我们有了 postman 以后,测试接口一般都直接在客户端完成,有些时候,我们可能需要通过代码实现,此时我们可以直接通过 Code 将 postman 实现的接口调用转为任意的代码如 js 、java、python 等,常见的转化如下:...
  • 项目的框架是springCloud 的一个服务,图片上传实际上就是用java的IO 流进行读写文件,给后台传递一个路径,后台通过浏览器链接到前端,将前端的图片数据拷贝的服务器的存储地址。1. 服务端保存图片的地址:...
  • postman实现多文件多参数提交

    千次阅读 2019-11-20 10:27:34
    多文件的话就是file0,file1,...后台Java实现代码 @PostMapping("/submitAuditTemplate/caiXinHttpResource") public Result submitAuditTemplateNew(@RequestParam Map<String,Object> map,MultipartHttp...
  • 一、实现Base64加密 1、点击添加->添加一个新的collection 2、在添加的collection中新建一个请求 3、点击右上角眼睛后,使用环境变量,可以使用环境变量(environment)也可以使用全局变量(global ...
  • 背景 项目组原有两个MongoDB的表,在经过不同的业务场景后分别去存储,后来由于个别业务调整,...实现样例 分别创建主文档和内嵌文档 mongodbTmeplate 测试验证 使用postman请求,之后查看MongoDB的结果: ...
  • 需要javapostman、newman、tomcat、jenkins环境 安装java: https://blog.csdn.net/qq_39680564/article/details/82768938 安装newman:https://blog.csdn.net/qq_39680564/article/details/84775303 安装tomcat:...
  • 1、java端代码 2、vo结构 3、postman构造
  • 上一章节Postman 实用接口测试系列 3 - 写测试介绍了如何在postman中编写测试用例,我们这一章将介绍如何使用postman实现数据驱动的测试。想象你一个场景,你需要测试一个注册的接口,那我们会需要测试几个不同的...

空空如也

空空如也

1 2 3 4 5 ... 14
收藏数 262
精华内容 104
关键字:

java实现postman

java 订阅