分享
  1. 首页
  2. 文章

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

books1958 · · 4065 次点击 · · 开始浏览
这是一个创建于 的文章,其中的信息可能已经有所发展或是发生改变。

本文是上一篇文章 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是一个简单的检查错误的函数。




有疑问加站长微信联系(非本文作者)

入群交流(和以上内容无关):加入Go大咖交流群,或添加微信:liuxiaoyan-s 备注:入群;或加QQ群:692541889

关注微信
4065 次点击
添加一条新回复 (您需要 后才能回复 没有账号 ?)
  • 请尽量让自己的回复能够对别人有帮助
  • 支持 Markdown 格式, **粗体**、~~删除线~~、`单行代码`
  • 支持 @ 本站用户;支持表情(输入 : 提示),见 Emoji cheat sheet
  • 图片支持拖拽、截图粘贴等方式上传

用户登录

没有账号?注册
(追記) (追記ここまで)

今日阅读排行

    加载中
(追記) (追記ここまで)

一周阅读排行

    加载中

关注我

  • 扫码关注领全套学习资料 关注微信公众号
  • 加入 QQ 群:
    • 192706294(已满)
    • 731990104(已满)
    • 798786647(已满)
    • 729884609(已满)
    • 977810755(已满)
    • 815126783(已满)
    • 812540095(已满)
    • 1006366459(已满)
    • 692541889

  • 关注微信公众号
  • 加入微信群:liuxiaoyan-s,备注入群
  • 也欢迎加入知识星球 Go粉丝们(免费)

给该专栏投稿 写篇新文章

每篇文章有总共有 5 次投稿机会

收入到我管理的专栏 新建专栏