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;
    }
}

以上!


免責聲明!

本站轉載的文章為個人學習借鑒使用,本站對版權不負任何法律責任。如果侵犯了您的隱私權益,請聯系本站郵箱yoyou2525@163.com刪除。



 
粵ICP備18138465號   © 2018-2025 CODEPRJ.COM