Golang+Android文件上传(多文件上传、附带请求参数)

本文是上一篇文章 Golang+Android(使用HttpURLConnection)实现文件上传 的升级版,实现多文件上传功能,并且附带http请求参数。

客户端代码:

    /**
     * 使用HttpURLConnection通过POST方式提交请求,并上传文件。
     *
     * @param actionUrl  访问的url
     * @param textParams 文本类型的POST参数(key:value)
     * @param filePaths  文件路径的集合
     * @return 服务器返回的数据,出现异常时返回 null
     */
    public static String postWithFiles(String actionUrl, Map<String, String> textParams, List<String> filePaths) {
        try {
            final String BOUNDARY = UUID.randomUUID().toString();
            final String PREFIX = "--";
            final String LINE_END = "\r\n";

            final String MULTIPART_FROM_DATA = "multipart/form-data";
            final String CHARSET = "UTF-8";

            URL uri = new URL(actionUrl);
            HttpURLConnection conn = (HttpURLConnection) uri.openConnection();

            //缓存大小
            conn.setChunkedStreamingMode(1024 * 64);
            //超时
            conn.setReadTimeout(5 * 1000);
            conn.setDoInput(true);
            conn.setDoOutput(true);
            conn.setUseCaches(false); 
            conn.setRequestMethod("POST");

            conn.setRequestProperty("connection", "keep-alive");
            conn.setRequestProperty("Charset", "UTF-8");
            conn.setRequestProperty("Content-Type", MULTIPART_FROM_DATA + ";boundary=" + BOUNDARY);

            // 拼接文本类型的参数
            StringBuilder textSb = new StringBuilder();
            if (textParams != null) {
                for (Map.Entry<String, String> entry : textParams.entrySet()) {
                    textSb.append(PREFIX).append(BOUNDARY).append(LINE_END);
                    textSb.append("Content-Disposition: form-data; name=\"" + entry.getKey() + "\"" + LINE_END);
                    textSb.append("Content-Type: text/plain; charset=" + CHARSET + LINE_END);
                    textSb.append("Content-Transfer-Encoding: 8bit" + LINE_END);
                    textSb.append(LINE_END);
                    textSb.append(entry.getValue());
                    textSb.append(LINE_END);
                }
            }

            DataOutputStream outStream = new DataOutputStream(conn.getOutputStream());
            outStream.write(textSb.toString().getBytes());

            //参数POST方式
            //outStream.write("userId=1&cityId=26".getBytes());

            // 发送文件数据
            if (filePaths != null) {
                for (String file : filePaths) {
                    StringBuilder fileSb = new StringBuilder();
                    fileSb.append(PREFIX).append(BOUNDARY).append(LINE_END);
                    fileSb.append("Content-Disposition: form-data; name=\"file\"; filename=\"" +
                            file.substring(file.lastIndexOf("/") + 1) + "\"" + LINE_END);
                    fileSb.append("Content-Type: application/octet-stream; charset=" + CHARSET + LINE_END);
                    fileSb.append(LINE_END);
                    outStream.write(fileSb.toString().getBytes());

                    InputStream is = new FileInputStream(file);
                    byte[] buffer = new byte[1024 * 8];
                    int len;
                    while ((len = is.read(buffer)) != -1) {
                        outStream.write(buffer, 0, len);
                    }

                    is.close();
                    outStream.write(LINE_END.getBytes());
                }
            }

            // 请求结束标志
            outStream.write((PREFIX + BOUNDARY + PREFIX + LINE_END).getBytes());
            outStream.flush();

            // 得到响应码
            int responseCode = conn.getResponseCode();
            BufferedReader br = new BufferedReader(new InputStreamReader(conn.getInputStream(), CHARSET));

            StringBuilder resultSb = null;
            String line;
            if (responseCode == 200) {
                resultSb = new StringBuilder();
                while ((line = br.readLine()) != null) {
                    resultSb.append(line).append("\n");
                }
            }

            br.close();
            outStream.close();
            conn.disconnect();

            return resultSb == null ? null : resultSb.toString();
        } catch (IOException e) {
            e.printStackTrace();
        }

        return null;
    }
服务器端代码:
//客户端上传多个文件,并带有请求参数
func handleUploadFile(w http.ResponseWriter, r *http.Request) {
	fmt.Println("client:", r.RemoteAddr, "method:", r.Method)

	r.ParseForm()
	r.ParseMultipartForm(32 << 20) //最大内存为32M

	//读取参数
	userId := r.FormValue("userId")
	cityId := r.FormValue("cityId")
	log.Println("userId=", userId, "cityId=", cityId)

	mp := r.MultipartForm
	if mp == nil {
		log.Println("not MultipartForm.")
		w.Write(([]byte)("不是MultipartForm格式"))
		return
	}

	fileHeaders, findFile := mp.File["file"]
	if !findFile || len(fileHeaders) == 0 {
		log.Println("file count == 0.")
		w.Write(([]byte)("没有上传文件"))
		return
	}

	for _, v := range fileHeaders {
		fileName := v.Filename
		file, err := v.Open()
		checkErrorV2(err, "Open file error."+fileName)
		defer file.Close()

		outputFilePath := "/home/admin/桌面/" + fileName
		writer, err := os.OpenFile(outputFilePath, os.O_WRONLY|os.O_CREATE, 0666)
		checkErrorV2(err, "Open local file error")
		io.Copy(writer, file)
	}

	msg := fmt.Sprintf("成功上传了%d个文件", len(fileHeaders))
	w.Write(([]byte)(msg))
}
注:checkErrorV2是一个简单的检查错误的函数。



  • 2
    点赞
  • 2
    收藏
    觉得还不错? 一键收藏
  • 4
    评论
评论 4
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值