任意java程序都可以是servlet吗_C#从Java servlet中获取文件流实现任意文件下载
目的:
從C#創(chuàng)建的客戶端中向Java創(chuàng)建的servlet提交請(qǐng)求(不知道這是否算作嚴(yán)格的CS架構(gòu)),servet返回一個(gè)文件流( 任意格式的文件 ),然后通過(guò)C#獲取該文件流并保存到本地,使得文件可以正常打開(kāi)并完整無(wú)缺。
發(fā)現(xiàn)問(wèn)題:
Java中的servlet代碼如下:
package servlet;
import javax.servlet.ServletException;
import javax.servlet.ServletOutputStream;
import javax.servlet.annotation.WebServlet;
import javax.servlet.http.HttpServlet;
import javax.servlet.http.HttpServletRequest;
import javax.servlet.http.HttpServletResponse;
import java.io.*;
@WebServlet(urlPatterns = "/update")
public class getUpdate extends HttpServlet{
@Override
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
// super.doGet(req, resp);
File file=new File("D:\\test.exe");
FileInputStream inputStream=new FileInputStream(file);
int i=inputStream.available();
byte[] data=new byte[i];
inputStream.read(data);
ServletOutputStream outputStream=resp.getOutputStream();
outputStream.write(data);
outputStream.flush();
outputStream.close();
inputStream.close();
}
@Override
protected void doPost(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
super.doPost(req, resp);
}
}
servlet的環(huán)境為本地,D盤下的test.exe是一個(gè)可執(zhí)行的winform程序,用于文件的完整性測(cè)試。
將以上代碼部署到tomcat后,直接在瀏覽器中輸入“http://localhost:8080/update”可以下載到名為update的文件,給update添加.exe后綴后直接打開(kāi)發(fā)現(xiàn)可以正常執(zhí)行,這表明該servlet并沒(méi)什么問(wèn)題。
客戶端的C#代碼如下:
using System;
using System.IO;
using System.Net;
namespace ServiceTest
{
class Program
{
static void Main(string[] args)
{
string url = "http://localhost:8080/update";
HttpWebRequest webRequest = (HttpWebRequest)WebRequest.Create(url);
WebResponse webResponse = webRequest.GetResponse();
Stream responseStream = webResponse.GetResponseStream();
FileStream fileStream = new FileStream("test.exe", FileMode.Create);
byte[] data = new byte[100000];
int count = responseStream.Read(data, 0, data.Length);
fileStream.Write(data, 0, count);
Console.WriteLine("OK");
fileStream.Close();
responseStream.Close();
}
}
}
剛開(kāi)始我覺(jué)得test.exe文件不過(guò)只有15kb,這里給出的byte[100000]一定綽綽有余。所以當(dāng)我執(zhí)行程序時(shí),發(fā)現(xiàn)控制臺(tái)可以正常輸出“OK”,但是在該項(xiàng)目目錄下的test.exe文件卻只有8kb:
test.exe屬性
而且很明顯,雙擊該文件無(wú)法執(zhí)行:
test.exe執(zhí)行結(jié)果
解決問(wèn)題:
然后我用Java寫了個(gè)測(cè)試代碼:
package test;
import java.io.*;
import java.net.HttpURLConnection;
import java.net.URL;
import java.net.URLConnection;
public class Test2 {
public static void main(String[] args) {
String url = "http://localhost:8080/update";
try {
URLConnection connection = new URL(url).openConnection();
HttpURLConnection httpURLConnection = (HttpURLConnection) connection;
InputStream inputStream = httpURLConnection.getInputStream();
int i = inputStream.available();
byte[] data = new byte[i];
inputStream.read(data);
File file = new File("D:\\test2.exe");
OutputStream outputStream = new FileOutputStream(file);
outputStream.write(data);
System.out.println("finish");
outputStream.close();
inputStream.close();
httpURLConnection.disconnect();
((HttpURLConnection) connection).disconnect();
} catch (Exception e) {
e.printStackTrace();
}
}
}
運(yùn)行后得到的test2.exe文件完全正常!
于是接下來(lái)分別對(duì)C#客戶端代碼和Java客戶端代碼進(jìn)行調(diào)試:
C#調(diào)試
Java調(diào)試
從上面兩張圖可以看出data內(nèi)容不盡相同,在C#中data[2]=144,但是在Java中data[2]=-112。原因是C#中的byte取值為0~255,而Java中的byte取值為-128~127。但這好像不是問(wèn)題的關(guān)鍵,關(guān)鍵是在C#中的8192行以后,數(shù)據(jù)全部為空,到此截?cái)唷?/p>
C#調(diào)試
掐指一算,8192/1024=8。這時(shí)才明白new byte[100000]的寫法是錯(cuò)誤的,而且是及其荒謬可笑的不符合程序員思想的不能容忍的應(yīng)當(dāng)被槍斃的錯(cuò)誤!
修正后的C#關(guān)鍵代碼如下:
byte[] data = new byte[1024];
int count;
while ((count = responseStream.Read(data, 0, data.Length)) != 0)
{
fileStream.Write(data, 0, count);
}
同時(shí)意識(shí)到servlet中的寫法也是不負(fù)責(zé)任的,當(dāng)要傳輸?shù)奈募^(guò)大時(shí),問(wèn)題就會(huì)顯現(xiàn)出來(lái),因此修改后的servlet關(guān)鍵代碼如下:
protected void doGet(HttpServletRequest req, HttpServletResponse resp) throws ServletException, IOException {
File file=new File("D:\\test.exe");
FileInputStream inputStream=new FileInputStream(file);
ServletOutputStream outputStream=resp.getOutputStream();
byte[] data=new byte[1024];
int count;
while ((count=inputStream.read(data,0,data.length))!=-1){
outputStream.write(data,0,count);
}
outputStream.flush();
outputStream.close();
inputStream.close();
}
總結(jié):
1.C#中的byte是無(wú)符號(hào)的,取值范圍為0~255;而Java中的byte是有符號(hào)的,取值范圍為-128~127。
2.C#中的byte[]最多只到8192,即8k,超出8192部分不會(huì)被存取。Java雖然沒(méi)有此限制,但是直接new一個(gè)長(zhǎng)度很長(zhǎng)的數(shù)組去保存文件流信息仍是極其不推薦的。
3.C#中public abstract int Read(byte[] buffer, int offset, int count)函數(shù)當(dāng)讀取到文件結(jié)尾時(shí)返回值為0;而Java中public int read(byte b[], int off, int len)返回值為-1。
4.C#中的StreamReader和StreamWriter只適合讀寫字符串,而不能用于處理二進(jìn)制文件。
總結(jié)
以上是生活随笔為你收集整理的任意java程序都可以是servlet吗_C#从Java servlet中获取文件流实现任意文件下载的全部?jī)?nèi)容,希望文章能夠幫你解決所遇到的問(wèn)題。
- 上一篇: java 铁三车强度如何_工欲善其事,必
- 下一篇: c#如何wmf图片转换成png图片_每日