通过HttpURLConnection连接上传文件和参数并接收

网上使用HttpURLConnection通过get或post请求传递参数或者传递文件的例子有很多。但是同时传递参数和文件,服务的并接收参数和文件的例子很少!此文将介绍同时发送参数和文件并接收。

1.HttpURLConnection简介

任何网络连接都需要经过socket才能连接,HttpURLConnection不需要设置socket,所以,HttpURLConnection并不是底层的连接,而是在底层连接上的一个请求。这就是为什么HttpURLConneciton只是一个抽象类,自身不能被实例化的原因。HttpURLConnection只能通过URL.openConnection()方法创建具体的实例。

虽然底层的网络连接可以被多个HttpURLConnection实例共享,但每一个HttpURLConnection实例只能发送一个请求。请求结束之后,应该调用HttpURLConnection实例的InputStream或OutputStream的close()方法以释放请求的网络资源,不过这种方式对于持久化连接没用。对于持久化连接,得用disconnect()方法关闭底层连接的socket。
简单来说,HttpURLConnection就是Java提供的发起HTTP请求的基础类库,提供了HTTP请求的基本能力

2.使用HttpURLConnection发送参数和文件

发送参数及文件

public String sendFileAndDataTest() throws Exception {

        String serverUrl = "http://localhost/payment-wxrefund/wxrefund/refund";
        
        Map<String, Object> reqData = new HashMap<>();
        reqData.put("out_trade_no", “out_trade_no”);
        reqData.put("transaction_id", “transaction_id”);
        
        // 获取到要上传的文件的输入流信息,通过ByteArrayOutputStream流转成byte[]
        File file = new File("D:\Download/2020-11-10包医微信账单.csv");
        BufferedInputStream bis = new BufferedInputStream(new FileInputStream(file));
        ByteArrayOutputStream baos = new ByteArrayOutputStream();

        byte[] body_data = null;
        int c = 0;
        byte[] buffer = new byte[8 * 1024];
        try {
            while ((c = bis.read(buffer)) != -1) {
                baos.write(buffer, 0, c);
                baos.flush();
            }
            body_data = baos.toByteArray();
            baos.close();
        } catch (IOException e) {
            e.printStackTrace();
        }

       // 调用自定义的post数据方法,提交表单数据及上传文件
        String result = sendFileData(serverUrl, reqData,  body_data, "utf-8");
    }


 private String sendFileData(String serverUrl, Map<String, Object> reqData,  byte[] body_data, String charset) throws IOException {
        // 设置三个常用字符串常量:换行、前缀、分界线(NEWLINE、PREFIX、BOUNDARY);
        final String NEWLINE = "\r\n";
        final String PREFIX = "--"; 
        final String BOUNDARY = "#"; 
        
        HttpURLConnection httpConn = null;
        BufferedInputStream bis = null;
        DataOutputStream dos = null;
        ByteArrayOutputStream baos = new ByteArrayOutputStream();
        try {
            // 实例化URL对象。调用URL有参构造方法,参数是一个url地址;
            URL urlObj = new URL(serverUrl);
            // 调用URL对象的openConnection()方法,创建HttpURLConnection对象;
            httpConn = (HttpURLConnection) urlObj.openConnection();
            // 调用HttpURLConnection对象setDoOutput(true)、setDoInput(true)、setRequestMethod("POST");
            httpConn.setDoInput(true);
            httpConn.setDoOutput(true);
            httpConn.setRequestMethod("POST");
            // 设置Http请求头信息;(Accept、Connection、Accept-Encoding、Cache-Control、Content-Type、User-Agent)
            httpConn.setUseCaches(false);
            httpConn.setRequestProperty("Connection", "Keep-Alive");
            httpConn.setRequestProperty("Accept", "*/*");
            httpConn.setRequestProperty("Accept-Encoding", "gzip, deflate");
            httpConn.setRequestProperty("Cache-Control", "no-cache");
            // 这个比较重要,按照上面分析的拼装出Content-Type头的内容
            httpConn.setRequestProperty("Content-Type",
                    "multipart/form-data; boundary=" + BOUNDARY);
            // 这个参数可以参考浏览器中抓出来的内容写,用chrome或者Fiddler抓吧看看就行
            httpConn.setRequestProperty(
                    "User-Agent",
                    "Mozilla/4.0 (compatible; MSIE 6.0; Windows NT 5.1; SV1; .NET CLR 2.0.50727; .NET CLR 3.0.04506.30)");
            // 调用HttpURLConnection对象的connect()方法,建立与服务器的真实连接;
            httpConn.connect();

            // 调用HttpURLConnection对象的getOutputStream()方法构建输出流对象;
            dos = new DataOutputStream(httpConn.getOutputStream());
            // 获取表单中上传控件之外的控件数据,写入到输出流对象(根据上面分析的抓包的内容格式拼凑字符串);
            if (reqData != null && !reqData.isEmpty()) { // 这时请求中的普通参数,键值对类型的,相当于上面分析的请求中的username,可能有多个
                for (Map.Entry<String, Object> entry : reqData.entrySet()) {
                    String key = entry.getKey(); // 键,相当于上面分析的请求中的username
                    Object value = reqData.get(key); // 值,相当于上面分析的请求中的sdafdsa
                    dos.writeBytes(PREFIX + BOUNDARY + NEWLINE); // 像请求体中写分割线,就是前缀+分界线+换行
                    dos.writeBytes("Content-Disposition: form-data; "
                            + "name=\"" + key + "\"" + NEWLINE); // 拼接参数名,格式就是Content-Disposition: form-data; name="key" 其中key就是当前循环的键值对的键,别忘了最后的换行
                    dos.writeBytes(NEWLINE); // 空行,一定不能少,键和值之间有一个固定的空行
                    dos.writeBytes(URLEncoder.encode(value.toString(), charset)); // 将值写入
                    // 或者写成:dos.write(value.toString().getBytes(charset));
                    dos.writeBytes(NEWLINE); // 换行
                } 
            }
            
            // 获取表单中上传附件的数据,写入到输出流对象(根据上面分析的抓包的内容格式拼凑字符串);
            if (body_data != null && body_data.length > 0) {
                dos.writeBytes(PREFIX + BOUNDARY + NEWLINE);// 像请求体中写分割线,就是前缀+分界线+换行
                String fileName = "2020-11-10包医微信账单";
                // 格式是:Content-Disposition: form-data; name="请求参数名"; filename="文件名"
                // 我这里吧请求的参数名写成了uploadFile,是死的,实际应用要根据自己的情况修改
                // 不要忘了换行
                dos.writeBytes("Content-Disposition: form-data; " + "name=\""
                        + "uploadFile" + "\"" + "; filename=\"" + fileName
                        + "\"" + NEWLINE);
                // 换行,重要!!不要忘了
                dos.writeBytes(NEWLINE);
                dos.write(body_data); // 上传文件的内容
                dos.writeBytes(NEWLINE); // 最后换行
            }
            dos.writeBytes(PREFIX + BOUNDARY + PREFIX + NEWLINE); 
            // 最后的分割线,与前面的有点不一样是前缀+分界线+前缀+换行,最后多了一个前缀
            dos.flush();

            // 调用HttpURLConnection对象的getInputStream()方法构建输入流对象;
            byte[] buffer = new byte[8 * 1024];
            int c = 0;
            // 调用HttpURLConnection对象的getResponseCode()获取客户端与服务器端的连接状态码。如果是200,则执行以下操作,否则返回null;
            if (httpConn.getResponseCode() == 200) {
                bis = new BufferedInputStream(httpConn.getInputStream());
                while ((c = bis.read(buffer)) != -1) {
                    baos.write(buffer, 0, c);
                    baos.flush();
                }
            }
            // 将输入流转成字节数组,返回给客户端。
            return new String(baos.toByteArray(), charset);
        } catch (Exception e) {
            e.printStackTrace();
        } finally {
            try {
                if (dos != null)
                    dos.close();
                if (bis != null)
                    bis.close();
                if (baos != null)
                    baos.close();
                httpConn.disconnect();
            } catch (Exception e) {
                e.printStackTrace();
            }
        }
        return null;
    }

接收参数及文件


    public Map<String, String> getFileAndData(HttpServletRequest request, HttpServletResponse response) throws Exception {
        // 获取file
        MultipartHttpServletRequest multiRequest = (MultipartHttpServletRequest)request;

        MultiValueMap<String, MultipartFile> multiFileMap = multiRequest.getMultiFileMap();
        List<MultipartFile> uploadFile1 = multiFileMap.get("uploadFile");

        MultipartFile multipartFile = uploadFile1.get(0);
        File file = File.createTempFile(multipartFile.getOriginalFilename(),".csv");
        multipartFile.transferTo(file);
        // 获取退款订单参数
        String out_trade_no = request.getParameter("out_trade_no");
		String transaction_id = request.getParameter("transaction_id");
    }

亲测可用,欢迎留言,希望对大家有帮助。

  • 2
    点赞
  • 13
    收藏
    觉得还不错? 一键收藏
  • 2
    评论
好的,针对你的问题,我可以给你提供一些思路和代码示例。 首先,你需要使用`HttpURLConnection`来实现文件上传。以下是一个上传文件的示例代码: ```java URL url = new URL(uploadUrl); HttpURLConnection connection = (HttpURLConnection) url.openConnection(); connection.setDoOutput(true); connection.setRequestMethod("POST"); connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary); DataOutputStream outputStream = new DataOutputStream(connection.getOutputStream()); outputStream.writeBytes("--" + boundary + "\r\n"); outputStream.writeBytes("Content-Disposition: form-data; name=\"file\";filename=\"" + fileName + "\"" + "\r\n"); outputStream.writeBytes("Content-Type: " + mimeType + "\r\n"); outputStream.writeBytes("\r\n"); outputStream.write(fileBytes); outputStream.writeBytes("\r\n"); outputStream.writeBytes("--" + boundary + "--" + "\r\n"); outputStream.flush(); outputStream.close(); ``` 在上面的代码中,`uploadUrl`是上传文件的接口地址,`boundary`是分隔符,`fileName`是文件名,`mimeType`是文件类型,`fileBytes`是文件的二进制数据。 接下来,你需要在Spring MVC中编写文件上传接口。以下是一个接收文件的示例代码: ```java @RequestMapping(value = "/upload", method = RequestMethod.POST) public ModelAndView upload(@RequestParam("file") MultipartFile file) throws IOException { String fileName = file.getOriginalFilename(); byte[] fileBytes = file.getBytes(); // do something with the file bytes return new ModelAndView("upload_success"); } ``` 在上面的代码中,`@RequestParam("file")`注解表示接收名为`file`的文件参数,并且使用`MultipartFile`类型来接收文件数据。`getOriginalFilename()`方法获取文件名,`getBytes()`方法获取文件二进制数据。 希望以上代码能够帮助到你!

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论 2
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值