任意java程序都可以是servlet吗_C#从Java servlet中获取文件流实现任意文件下载
目的:
從C#創建的客戶端中向Java創建的servlet提交請求(不知道這是否算作嚴格的CS架構),servet返回一個文件流( 任意格式的文件 ),然后通過C#獲取該文件流并保存到本地,使得文件可以正常打開并完整無缺。
發現問題:
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的環境為本地,D盤下的test.exe是一個可執行的winform程序,用于文件的完整性測試。
將以上代碼部署到tomcat后,直接在瀏覽器中輸入“http://localhost:8080/update”可以下載到名為update的文件,給update添加.exe后綴后直接打開發現可以正常執行,這表明該servlet并沒什么問題。
客戶端的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();
}
}
}
剛開始我覺得test.exe文件不過只有15kb,這里給出的byte[100000]一定綽綽有余。所以當我執行程序時,發現控制臺可以正常輸出“OK”,但是在該項目目錄下的test.exe文件卻只有8kb:
test.exe屬性
而且很明顯,雙擊該文件無法執行:
test.exe執行結果
解決問題:
然后我用Java寫了個測試代碼:
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();
}
}
}
運行后得到的test2.exe文件完全正常!
于是接下來分別對C#客戶端代碼和Java客戶端代碼進行調試:
C#調試
Java調試
從上面兩張圖可以看出data內容不盡相同,在C#中data[2]=144,但是在Java中data[2]=-112。原因是C#中的byte取值為0~255,而Java中的byte取值為-128~127。但這好像不是問題的關鍵,關鍵是在C#中的8192行以后,數據全部為空,到此截斷。
C#調試
掐指一算,8192/1024=8。這時才明白new byte[100000]的寫法是錯誤的,而且是及其荒謬可笑的不符合程序員思想的不能容忍的應當被槍斃的錯誤!
修正后的C#關鍵代碼如下:
byte[] data = new byte[1024];
int count;
while ((count = responseStream.Read(data, 0, data.Length)) != 0)
{
fileStream.Write(data, 0, count);
}
同時意識到servlet中的寫法也是不負責任的,當要傳輸的文件過大時,問題就會顯現出來,因此修改后的servlet關鍵代碼如下:
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();
}
總結:
1.C#中的byte是無符號的,取值范圍為0~255;而Java中的byte是有符號的,取值范圍為-128~127。
2.C#中的byte[]最多只到8192,即8k,超出8192部分不會被存取。Java雖然沒有此限制,但是直接new一個長度很長的數組去保存文件流信息仍是極其不推薦的。
3.C#中public abstract int Read(byte[] buffer, int offset, int count)函數當讀取到文件結尾時返回值為0;而Java中public int read(byte b[], int off, int len)返回值為-1。
4.C#中的StreamReader和StreamWriter只適合讀寫字符串,而不能用于處理二進制文件。
總結
以上是生活随笔為你收集整理的任意java程序都可以是servlet吗_C#从Java servlet中获取文件流实现任意文件下载的全部內容,希望文章能夠幫你解決所遇到的問題。
- 上一篇: java 铁三车强度如何_工欲善其事,必
- 下一篇: c#如何wmf图片转换成png图片_每日