Java模拟http上传文件请求(HttpURLConnection,HttpClient4.4,RestTemplate)
先上代码:
public void uploadToUrl(String fileId, String fileSetId, String formUrl) throws Throwable { String urlStr = MyServiceConfig.getUrl() + UPLOAD_URL; String fileName = FileUtils.getFileName(formUrl); long fileSize = getFileSize(formUrl); String uri = UriComponentsBuilder.fromUriString(urlStr).queryParam("fileId", fileId).build().encode().toString(); logger.debug("文件上传请求路径:{}", uri); // 获取文件输入流 InputStream in = getFileInputString(formUrl); if (null != in) { URL urlObj = new URL(uri); HttpURLConnection con = (HttpURLConnection) urlObj.openConnection(); con.setRequestMethod("POST"); // 设置关键值,以Post方式提交表单,默认get方式 con.setDoInput(true); con.setDoOutput(true); con.setUseCaches(false); // post方式不能使用缓存 // 设置请求头信息 con.setRequestProperty("Connection", "Keep-Alive"); con.setRequestProperty("Charset", "UTF-8"); // 设置边界 String BOUNDARY = "----------" + System.currentTimeMillis(); con.setRequestProperty("Content-Type", "multipart/form-data; boundary=" + BOUNDARY); // 请求正文信息 // 第一部分: StringBuilder sb = new StringBuilder(); sb.append("--"); // 必须多两道线 sb.append(BOUNDARY); sb.append("\r\n"); sb.append("Content-Disposition: form-data;name=\"file\";filename=\"" + fileName + "\"\r\n"); if(!fileName.endsWith("mp4")){ sb.append("Content-Type:image/jpeg\r\n\r\n"); }else if(){ sb.append("Content-Type:video/mp4\r\n\r\n"); } //未知文件类型,以流的方式上传 //sb.append("Content-Type:application/octet-stream\r\n\r\n"); byte[] head = sb.toString().getBytes("utf-8"); // 获得输出流 OutputStream out = new DataOutputStream(con.getOutputStream()); // 输出表头 out.write(head); // 文件正文部分 // 把文件已流文件的方式 推入到url中 DataInputStream dataIn = new DataInputStream(in); int bytes = 0; byte[] bufferOut = new byte[1024]; while ((bytes = dataIn.read(bufferOut)) != -1) { out.write(bufferOut, 0, bytes); } in.close(); // 结尾部分 byte[] foot = ("\r\n--" + BOUNDARY + "--\r\n").getBytes("utf-8");// 定义最后数据分隔线 out.write(foot); out.flush(); out.close(); // 读取返回数据 StringBuffer strBuf = new StringBuffer(); BufferedReader reader = new BufferedReader(new InputStreamReader(con.getInputStream())); String line = null; while ((line = reader.readLine()) != null) { strBuf.append(line).append("\n"); } logger.debug("文件上传返回信息{}",strBuf.toString()); reader.close(); con.disconnect(); con = null; } else { throw new Throwable("获取文件流失败,文件下载地址url=" + formUrl); } } // 获取文件大小 public InputStream getFileInputString(String formUrl) throws Throwable { URL urlPath = new URL(formUrl); HttpURLConnection conn = (HttpURLConnection) urlPath.openConnection(); conn.setConnectTimeout(5000); conn.setRequestMethod("GET"); int status = conn.getResponseCode(); if (status == 200) { return conn.getInputStream(); } return null; } //获取文件大小 public long getFileSize(String formUrl) throws Throwable{ URL urlPath = new URL(formUrl); HttpURLConnection conn = (HttpURLConnection)urlPath.openConnection(); conn.setConnectTimeout(downloadTimeout); conn.setRequestMethod("GET"); int status = conn.getResponseCode(); if(status==200){ return conn.getContentLengthLong(); } return 0; }
public static String getFileName(String fileFullPath) {
fileFullPath = fileFullPath.replace("/", "\\");
return fileFullPath.substring(fileFullPath.lastIndexOf("\\") + 1,
fileFullPath.length());
}
public static String getFileNameWithoutSuffix(String fileFullPath) {
fileFullPath = fileFullPath.replace("/", "\\");
return fileFullPath.substring(fileFullPath.lastIndexOf("\\") + 1,
fileFullPath.lastIndexOf("."));
}
代码逻辑:
1、从访问文件的url中获取文件流和文件大小;
2、模拟http上传文件post请求;
1》.打开httpurlconnection连接,设置关键值:重点是设置请求方法post和设置不缓存;
2》.设置请求头,设置边界;重点是Content-Type;
3》.设置请求正文,比较复杂,参照代码;
4》.获取返回值;
二、使用httpClient4.4上传文件:
//上传实体文件 public static void upload(String url,String filePath) throws Exception{ HttpPost httpPost = new HttpPost(url); httpPost.setHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) " + "AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/62.0.3202.89 Safari/537.36"); httpPost.setHeader("Accept-Language","zh-cn,zh;q=0.5"); httpPost.setHeader("Accept-Charset","GBK,utf-8;q=0.7,*;q=0.7"); httpPost.setHeader("Connection","keep-alive"); MultipartEntityBuilder mutiEntity = MultipartEntityBuilder.create(); File file = new File(filePath); //File file = new File("C:\\Users\\\\Desktop\\20171002中士.mp4"); //mutiEntity.addTextBody("filename","1问题.mp4"); mutiEntity.addPart("file", new FileBody(file)); CloseableHttpClient httpClient = HttpClients.createDefault(); httpPost.setEntity(mutiEntity.build()); HttpResponse httpResponse = httpClient.execute(httpPost); HttpEntity httpEntity = httpResponse.getEntity(); String content = EntityUtils.toString(httpEntity); System.out.println(content); }
三、上传文件流: 重点是mode的设置,这里卡了半天;
//上传文件流 public static void upload(String url,InputStream in) throws Exception{ HttpPost httpPost = new HttpPost(url); httpPost.setHeader("User-Agent","Mozilla/5.0 (Windows NT 10.0; Win64; x64) " + "AppleWebKit/537.36 (KHTML, like Gecko) " + "Chrome/62.0.3202.89 Safari/537.36"); httpPost.setHeader("Accept-Language","zh-cn,zh;q=0.5"); httpPost.setHeader("Accept-Charset","GBK,utf-8;q=0.7,*;q=0.7"); httpPost.setHeader("Connection","keep-alive"); MultipartEntityBuilder mutiEntity = MultipartEntityBuilder.create(); //mutiEntity.addTextBody("filename","16有问题.mp4"); mutiEntity.setMode(HttpMultipartMode.BROWSER_COMPATIBLE); mutiEntity.addBinaryBody("uploadFile", in, ContentType.create("multipart/form-data"), "16有问题.mp4"); CloseableHttpClient httpClient = HttpClients.createDefault(); httpPost.setEntity(mutiEntity.build()); HttpResponse httpResponse = httpClient.execute(httpPost); HttpEntity httpEntity = httpResponse.getEntity(); String content = EntityUtils.toString(httpEntity); System.out.println(content); }
四、使用RestTemplate:
public static void uploadFile(String url,File file){ RestTemplate template = new RestTemplate(); ClientHttpRequestFactory clientFactory = new HttpComponentsClientHttpRequestFactory(); template.setRequestFactory(clientFactory); URI uri = UriComponentsBuilder.fromUriString(url).build().encode().toUri(); FileSystemResource resource = new FileSystemResource(file); MultiValueMap<String, Object> param = new LinkedMultiValueMap<>(); param.add("file", resource); //param.add("fileName", "问题.mp4"); org.springframework.http.HttpEntity<MultiValueMap<String, Object>> httpEntity = new org.springframework.http.HttpEntity<MultiValueMap<String, Object>>(param); ResponseEntity<String> responseEntity = template.exchange(uri, HttpMethod.POST, httpEntity, String.class); System.out.println("文件上传成功,返回:" + responseEntity.getBody()); }
上传大文件设置请求工厂类是否应用缓冲请求正文内部,默认值为true,当post或者put大文件的时候会造成内存溢出情况,设置为false将数据直接流入底层HttpURLConnection。
public int uploadFile(String url, File file) { RestTemplate template = new RestTemplate(); //ClientHttpRequestFactory clientFactory = new HttpComponentsClientHttpRequestFactory(); SimpleClientHttpRequestFactory clientFactory = new SimpleClientHttpRequestFactory(); clientFactory.setBufferRequestBody(false); template.setRequestFactory(clientFactory); URI uri = UriComponentsBuilder.fromUriString(url).build().encode().toUri(); FileSystemResource resource = new FileSystemResource(file); MultiValueMap<String, Object> param = new LinkedMultiValueMap<>(); param.add("file", resource); // param.add("fileName", "问题.mp4"); org.springframework.http.HttpEntity<MultiValueMap<String, Object>> httpEntity = new org.springframework.http.HttpEntity<MultiValueMap<String, Object>>( param); ResponseEntity<String> responseEntity = template.exchange(uri, HttpMethod.POST, httpEntity, String.class); logger.debug("文件上传成功,返回:{},状态码:{}",responseEntity.getBody(),responseEntity.getStatusCodeValue()); return responseEntity.getStatusCodeValue(); }
RestTemplate上传文件流:不建议用
这个比较麻烦,先看代码吧;
public static void uploadFile(String url,InputStream in){ RestTemplate template = new RestTemplate(); ClientHttpRequestFactory clientFactory = new HttpComponentsClientHttpRequestFactory(); template.setRequestFactory(clientFactory); URI uri = UriComponentsBuilder.fromUriString(url).build().encode().toUri(); // InputStreamResource resource = new InputStreamResource(in); MultiValueMap<String, Object> param = new LinkedMultiValueMap<>(); param.add("file", new MultipartFileResource(in, "test")); //param.add("fileName", "问题.mp4"); HttpHeaders headers = new HttpHeaders(); headers.setContentType(MediaType.MULTIPART_FORM_DATA); org.springframework.http.HttpEntity<MultiValueMap<String, Object>> httpEntity = new org.springframework.http.HttpEntity<MultiValueMap<String, Object>>(param,headers); List<HttpMessageConverter<?>> messageConverters = template.getMessageConverters(); for (int i = 0; i < messageConverters.size(); i++) { HttpMessageConverter<?> messageConverter = messageConverters.get(i); if ( messageConverter.getClass().equals(ResourceHttpMessageConverter.class) ) messageConverters.set(i, new ResourceHttpMessageConverterHandlingInputStreams()); } ResponseEntity<String> responseEntity = template.exchange(uri, HttpMethod.POST, httpEntity, String.class); System.out.println("文件上传成功,返回:" + responseEntity.getBody()); }
这是修改后的,添加了转换器,因为添加之前会报错,文件流读了两次,其中一次是读取文件大小contentLength;
package com.my.upload; import java.io.IOException; import java.io.InputStream; import org.springframework.core.io.InputStreamResource; public class MultipartFileResource extends InputStreamResource { private final String filename; public MultipartFileResource(InputStream inputStream, String filename) { super(inputStream); this.filename = filename; } @Override public String getFilename() { return this.filename; } @Override public long contentLength() throws IOException { return -1; // we do not want to generally read the whole stream into memory ... } } package com.my.upload; import java.io.IOException; import org.springframework.core.io.Resource; import org.springframework.http.MediaType; import org.springframework.http.converter.ResourceHttpMessageConverter; public class ResourceHttpMessageConverterHandlingInputStreams extends ResourceHttpMessageConverter { @Override protected Long getContentLength(Resource resource, MediaType contentType) throws IOException { Long contentLength = super.getContentLength(resource, contentType); return contentLength == null || contentLength < 0 ? null : contentLength; } }
以上!