1. 程式人生 > >使用HttpURLConnection的put或者post請求上傳檔案

使用HttpURLConnection的put或者post請求上傳檔案

HttpURLConnection為java本身提供的傳送http請求的工具,今天遇到需要用put請求上傳檔案的需求,記錄下:

首先分析下put請求的格式,使用postman的put請求傳送一個檔案,由於現在有springboot,實現一個接受put請求傳送檔案的伺服器很簡單,可以用來測試分析。

postman分析的請求如下:
這裡寫圖片描述

首先上面一部分為請求頭的資料,裡面需要注意的點是Content-type,因為上傳檔案,所以型別為Multipart/form-data, 後面boundary為下面資料的分隔字串,隨機產生的。

然後分析下面資料,+表示字串拼接
首先是一個分割字串
格式為 – + boundary + \r\n
然後是Content-Disposition:form-data; + name=”file”; + filename=“檔名” + \r\n
這裡的name值是輸入框input的name,filename值為檔名,這兩個引數都是選填,但是不填的話會影響後臺引數的接收。
接下來是Content-Type: text/plain + \r\n
然後\r\n

接下來就是檔案資料部分,不多解釋,需要注意的是檔案寫入完了以後要加回車機\r\n

然後是請求資料結束分割線,格式為
\r\n + – + boundary + – + \r\n

下面完整寫一遍資料格式,指定boundary為wk-2519775

--wk-2519775\r\n
Content-Disposition:form-data; name="file"; filename=“test.txt” \r\n
Content-Type: text/plain\r\n
\r\n

資料部分......\r\n

\r\n--wk-2519775--\r\n

下面為實現程式碼:

public class HttpTool {
    private static final String nextLine = "\r\n";
    private static final String twoHyphens = "--";
    //分割線  隨便寫一個
    private static final String boundary = "wk_file_2519775";
    /**
     * 生成http連線
     * @param method http請求方式
     * @return httpURLConnection
     * @throws
IOException 連線生成失敗 */
private static HttpURLConnection createConnection(String urlPath, String method) throws IOException { URL url = new URL(urlPath); HttpURLConnection httpURLConnection = (HttpURLConnection) url.openConnection(); httpURLConnection.setRequestMethod(method); httpURLConnection.setRequestProperty("Charsert", "UTF-8"); return httpURLConnection; } /** * 多檔案上傳 * @param files 檔案 */ public static void uploadFiles(File[] files){ String url = "http://localhost:8080/file"; for (File file : files){ uploadFile(file, url); } } /** * 上傳檔案 * @param file 檔案 * @param url 請求路徑 */ private static void uploadFile(File file, String url){ HttpURLConnection connection = null; OutputStream outputStream = null; FileInputStream inputStream = null; try { //獲取HTTPURLConnection連線 connection = createConnection(url, "PUT"); //執行寫入預設為false,置為true connection.setDoOutput(true); //禁用快取 connection.setUseCaches(false); //設定接收編碼 connection.setRequestProperty("Accept-Charset", "utf-8"); //開啟長連線可以持續傳輸 connection.setRequestProperty("Connection", "keep-alive"); //設定請求引數格式以及boundary分割線 connection.setRequestProperty("Content-Type", "multipart/form-data;boundary=" + boundary); //設定接收返回值的格式 connection.setRequestProperty("Accept", "application/json"); //開啟連線 connection.connect(); //獲取http寫入流 outputStream = new DataOutputStream(connection.getOutputStream()); //分隔符頭部 String header = twoHyphens + boundary + nextLine; //分隔符引數設定 header += "Content-Disposition: form-data;name=\"file\";" + "filename=\"" + file.getName() + "\"" + nextLine + nextLine; //寫入輸出流 outputStream.write(header.getBytes()); //讀取檔案並寫入 inputStream = new FileInputStream(file); byte[] bytes = new byte[1024]; int length; while ((length = inputStream.read(bytes))!= -1){ outputStream.write(bytes, 0, length); } //檔案寫入完成後加回車 outputStream.write(nextLine.getBytes()); //寫入結束分隔符 String footer = nextLine + twoHyphens + boundary + twoHyphens + nextLine; outputStream.write(footer.getBytes()); outputStream.flush(); //檔案上傳完成 InputStream response = connection.getInputStream(); InputStreamReader reader = new InputStreamReader(response); while (reader.read() != -1){ System.out.println(new String(bytes, "UTF-8")); } if (connection.getResponseCode() == HttpURLConnection.HTTP_OK){ System.out.println(connection.getResponseMessage()); }else { System.err.println("上傳失敗"); } } catch (IOException e) { e.printStackTrace(); } finally { try { if (outputStream != null){ outputStream.close(); } if (inputStream != null){ inputStream.close(); } if (connection != null){ connection.disconnect(); } } catch (IOException e) { e.printStackTrace(); } } } }

post請求上傳檔案也是一樣的,生成httpurlconnection連線時請求方式設為POST即可。

順便附上springboot的接收程式碼:

@SpringBootApplication
public class SpringBootMain {
    public static void main(String[] args) {
        SpringApplication.run(SpringBootMain.class);
    }
}
@RestController
public class PutController {

    @PutMapping("/file")
    public String getPutFile(MultipartFile file){
        System.out.println(file.getOriginalFilename());
        return "{\"name\" : 111 }";
    }

    @PostMapping("/file")
    public String getPostFile(MultipartFile file){
        System.out.println(file.getOriginalFilename());
        return "{\"name\" : 111 }";
    }
}